模型对象里面的抽象工厂?

时间:2014-02-25 15:50:15

标签: c++ model-view-controller

我有一些Model类和一个controller(manager)类。理想情况下,控制器需要处理具体的模型类型而不进行向下转换(这似乎是“正确的”)。我想到了访客模式和抽象工厂模式。以下是我的模型层次结构的示例:

class Animal {};
class Dog : public Animal {};
class Cat : public Animal {};

当我的解析器处理我们的数据文件(XML)时,某些元素类型映射到不同(但相关)的派生类型。在我的例子中,我们的XML定义了不同的动物,我们将适当的具体类型映射到每个动物(因为它们持有的数据各不相同,我想通过序列化类中的工厂方法避免单片“动物”类作为联合)。但是,它们存储为控制器中Animal个对象的列表,因此无法知道哪些是猫,哪些是狗。

当控制器需要以不同于Dogs的方式处理Cats时,我觉得我们可以采取一些方法。

  1. 控制器执行类型(dynamic_cast)的向下转换或检查虚拟类型成员以确定对象是否为cat,然后处理cat。和狗一样。我真的不喜欢这个解决方案。
  2. 利用抽象工厂模式,以便每个模型知道如何为每种动物类型创建相应的Controller对象。例如,Model::Cat有一个名为CreateControllerObject()(多态)的成员,并返回CatController类。请注意,对此解决方案感到错误的部分是Model::Cat类将具有一些业务逻辑,例如在我们知道可以创建cat之前将执行的某些检查。通常,模型对象应该是“哑数据”,因此我不确定是否可以使用“智能”模型。
  3. 直接在Model类上使用访问者模式,但这涉及在模型中放入大量的控制器逻辑,这就是我建议#2的原因。至少在#2情况下,可以访问相应的具体动物控制器类。
  4. 我不确定如何实现它,所以我想从SO社区获得一些设计思路。我自己想出的所有解决方案都没有感觉到正确,尽管#2感觉最正确并且大致朝着正确的方向前进。

1 个答案:

答案 0 :(得分:1)

您可以使用双重发送
http://en.wikipedia.org/wiki/Double_dispatch

class Controller
{
public:
   void update_animal(Dog &dog) { ... }
   void update_animal(Cat &cat) { ... }
};

class Dog : public Animal
{
public:
    virtual void update(Controller &controller)
    {
        controller.update_animal( *this );
    }
}
// same for Cat