2014-01-10 58 views
1

我有典型的班级设计问题,我想征求意见。班级设计的选择

让我们假设我有一个基类Animal。从这堂课我得到几类特定的动物。我对他们的相互作用感兴趣。由于它们的相互作用可能因动物而异,我所做的就是创建具有纯虚函数的基类,即抽象类:

class dog;

class cat;

class bird;

类动物{

私人:

INT腿;

公共:

虚拟无效相互作用(const的狗&)= 0;

virtual void Interact(const cat &)= 0;

virtual void Interact(const bird &)= 0;

};

然后,对于每个特定的动物,我创建一个Animal类的派生类。例如:

类犬:公共动物{

//与其他动物的相互作用的执行情况:

无效互动(常量狗&对象){...身体...};

void Interact(const cat & object){... body ...};

void Interact(const bird & object){... body ...};

};

类似于猫和鸟类。 现在我关心的是鸟类。鸟可以飞行,并有狗和猫没有的额外变量/方法。什么将是一个聪明的方式来管理呢?例如,蛮力的方法是增加基类动物额外的方法和变量,如int wingsvoid fly()。重点是他们不会被狗和猫班使用。它不干净。 也许另一种方式是竟被宣布从动物派生类FlyingAnimal:

类FlyingAnimal:公共动物{

私人:

INT翅膀;

public:

void Fly();

};

,然后我可以从这个代替动物创造一流的小鸟:

类鸟:公开FlyingAnimal {

身体和定义无效互动(...)的...

};

您对此有何看法?也许你有另一个建议。

非常感谢提前! Xtof

+0

你的“交互”方法应该做什么,以及动物与之交互的行为方式有什么不同? – Philipp

回答

1

我认为你做错的第一件事是在基类的接口中有派生类。 您应该使用Visitor pattern。您可以为所有三个动物课程创建通用互动访问者或三位独立访问者。然后你提供你想与之交互的动物作为构造函数参数。

+0

是的,如果可能不是最好的,那么在基类的接口中有派生类。我不知道访客模式。我通过Google搜索寻找了一些例子。这不是微不足道的理解......但我认为我的想法......或多或少!我想我需要一些很好的例子。你有一些吗?我所理解的是,它允许双重调度,即做的动作取决于两个对象,而不仅仅是参数。正确吗? –

2

对于每种可能的其他动物,如果你只有三个类别,但当你添加老鼠,兔子,老虎,老鼠,辣酱玉米饼馅,袋熊,海豚,犰狳和斑马时,笨拙,因为每当你添加一个新的动物,你需要编辑每个现有的类来添加一个新的交互方法。这不是面向对象的编程应该如何。 OOP的目的是,您可以简单地添加一个新类,所有其他类可以立即使用它,而无需进行任何修改。

因此,您应该以更普遍的方式处理交互。为什么一只猫会捕捉一只老鼠或一只鸟,而不是一只狗?当我要对付一只带有smibblat的猫时会发生什么? (一个smibblat是一个长约5厘米的小而蓬松的四条腿的食草哺乳动物,我刚刚编写并编写了一个class Smibblat: public Animal)。即使这只猫以前从未见过Smibblat,也会尝试追捕它,因为它符合它的猎物模式。猫对所有的动物都是危险的,它们比自己小1和2。

当您将添加一个抽象getSize()和抽象getSpeed()方法类动物,你可以有这样的方法:

void Cat::interact(const Animal & other) { 
    if (other.getSpeed() < this.getSpeed() && 
     other.getSize() < this.getSize()) { 
     this.eat(other); 
    } 
} 

它可以应用到创建任何新的动物。 Cat类将不再依赖于其他动物子类。它只依赖于动物,它提供了所有决定是否吃另一只动物的方法。

+0

是的,你是对的。我做到这一点,每次创建一个新的派生类时,我都必须编辑每个类。此外,我将不得不编辑基类,这不利于维护或如果我想发布代码。用户将不得不编辑基类,这是不友好的...但是,你提出的解决方案不是我要找的。我想避免课堂中的'如果'。 –