Vid*_*dak 5 c++ oop algorithm inheritance design-patterns
假设我们有最简单的结构,类Component,Leaf : Component和Composite : Component.Leaf类的每个对象都有一个int id赋予它标识的对象.复合类会像:
class Composite : public Component
{
public:
void removeComponent(Component*);
// other stuff
private:
std::vector<Component*> coll;
};
Run Code Online (Sandbox Code Playgroud)
和叶班一样:
class Leaf : public Component
{
public:
//stuff
int getID();
private:
int id;
};
Run Code Online (Sandbox Code Playgroud)
问题是如何定义功能removeComponent(Component* cmp).cmp实际上是一个Leaf,但我需要访问Component矢量coll,所以它需要是一个Component(我认为).removeComponent方法接受一个Leaf对象,并从整个结构中删除具有相同ID的所有其他Leaves.
现在,我想到了两种方式(两者都不起作用:P):
第一
void Composide::removeComponent(Component* cmp)
{
std::vector<Component*>::const_iterator it;
for(it = coll.begin(); it != coll.end(); ++it)
{
(*it)->removeComponent(cmp);
// where removeComponent is defined as virtual in Component, but
// the problem is that Leaf cannot erase itself from the collection
}
}
Run Code Online (Sandbox Code Playgroud)
第二
void Composide::removeComponent(Component* cmp)
{
std::vector<Component*>::const_iterator it;
for(it = coll.begin(); it != coll.end(); ++it)
{
if((*it)->equals(*cmp))
it = erase(it);
// But here I can't define equals function for Composite elements,
// so then I'd have to make functions which return the type of Component,
// and in case of Composite call recursively the function and
// in the case of Leaf call the equals() function and erase if needed.
// This however looks like really bad OOP practice, and I'd like to avoid
// using those methods which return type..
}
}
Run Code Online (Sandbox Code Playgroud)
必须有一个整洁,美好的方式来做到这一点.我认为该方法应该看起来像上面提到的第一种方式,只是我真的不知道如何启用Leaf从向量中删除自己.请帮帮我?:)
您似乎对到底是什么感到困惑Component。它是某个业务对象,还是代表树节点的类?如果它是一个树节点,那么所有树节点应该支持相同的操作以允许轻松递归。
因此,我会将 的定义移至removeComponent()基Component类并使其成为虚拟的。您可以在 中提供一个空的实现Component。
那么您的复合实现就很简单:
void Composide::removeComponent(Component* cmp)
{
std::vector<Component*>::const_iterator it;
for(it = coll.begin(); it != coll.end(); ++it)
{
if((*it)->equals(*cmp))
it = erase(it);
else
(*it)->removeComponent(cmp);
}
}
Run Code Online (Sandbox Code Playgroud)
编辑:关于 ID
同样,我认为您可能混淆了两个概念:组件 id 和组件。Component(也许改名为会更好TreeItem?)
您当前的removeComponent()函数采用一个Component指针,从而推断任何Component可以从树中删除(包括Composites)。这对我来说似乎是正确的。您可能很需要删除Composites. 因此,您可以简单地比较指针。
但是,您似乎正在比较仅Leafs具有的 Id(通过假定的相等重载)。
如果您想提供一个按 Id 删除的附加函数,那么我也将 GetID() 函数移至基Component类,并与之进行比较。Composite对象可以返回 -1 或其他一些空标记。
例如。
void Composite::getID()
{
return -1;
}
void Composide::removeComponent(Component* cmp)
{
std::vector<Component*>::const_iterator it;
for(it = coll.begin(); it != coll.end(); ++it)
{
if((*it) == cmp)
it = erase(it);
else
(*it)->removeComponent(cmp);
}
}
void Composite::removeComponentById(int id)
{
std::vector<Component*>::const_iterator it;
for(it = coll.begin(); it != coll.end(); ++it)
{
if((*it)->getID() == id)
it = erase(it);
else
(*it)->removeComponentById(id);
}
}
Run Code Online (Sandbox Code Playgroud)