可选功能的设计模式?

时间:2009-05-21 09:23:25

标签: c++ design-patterns inheritance derived-class

我有一个派生子类继承的基本类,它包含所有派生类应该相同的基本函数:

class Basic {
public:
    Run() {
        int input = something->getsomething();
        switch(input)
        {
            /* Basic functionality */
            case 1:
                doA();
                break;
            case 2:
                doB();
                break;
            case 5:
                Foo();
                break;
        }
    }
};

现在,基于派生类,我想向交换机“添加”更多case语句。我有什么选择?我可以声明虚函数,只在将要使用它们的派生类中定义它们:

class Basic {
protected:
    virtual void DoSomethingElse();
public:
    Run() {
        int input = something->getsomething();
        switch(input)
        {
            /* Basic functionality */
            ...

            case 6:
                DoSomethingElse();
        }
    }
};


class Derived : public Basic {
protected:
    void DoSomethingElse() { ... }
}

但这意味着在更改任何派生类中的函数时,我必须编辑我的基类以反映这些更改。

是否有专门针对此类问题的设计模式?我购买了许多关于设计模式的书籍,但我是在“按需”的基础上研究它们,所以我不知道是否有这样的模式我正在寻找。

6 个答案:

答案 0 :(得分:4)

我认为您需要的模式是责任链或者策略与动态调用表相结合......

答案 1 :(得分:4)

您可能会发现阅读Chain of responsibility pattern并以这种方式重新考虑您的解决方案非常有用。

您也可以将'doRun'声明为受保护的方法,并在基本默认情况下调用它。

default:
   doRun(input);

在派生类中定义doRun。

这就是所谓的Template Method pattern

答案 2 :(得分:1)

解决这个问题的正常方法是使用工厂。概括地说:

  • 创建提供功能的相关类的层次结构。
  • 创建一个工厂类,它接受输入并根据输入创建正确类的实例

现在增加奖励积分:

  • 创建一个在工厂中对类进行注册的方案 - 您需要指定输入和类的类型来处理它

现在,当需要新输入时,您只需派生一个新类并将其注册到工厂。对switch语句的需求消失了。

答案 3 :(得分:1)

  

但这意味着在改变时   任何派生类中的函数,I   必须编辑我的基类   反映这些变化。

为什么会这样?

我点评你的评论 - 如果你选择这种方法,你就会遇到这些问题。其他人已经发布了建议其他解决方案的答案 - 我会检查这些解决方案以确定它们是否对您有所帮助。

答案 4 :(得分:1)

如果您的选择器值只是小整数,我会用查找表替换case语句。 (在这种情况下的操作将需要编码为一个函数,因此您可以将函数指针放在表中)。然后继承的类只能向表中添加条目。 (我猜表必须是一个实例属性,它不能是静态的)。

科林

答案 5 :(得分:1)

А简单的解决方案:

class Basic {
  public:
    void Run() {
      const int input = ...
      if (!(BaseProcess(input) || Process(input))) ...
    }

    vitual bool Process(int input) { return false; }

    bool BaseProcess(int input) {
      switch(input) {
    ...
        default: return false;
      }
      return true;
    }
...

...然后在子类'Process()中实现其他案例。 如果你需要支持2个以上的级别(即子类增加甚至更多的情况),那么你需要一个动态的调度表。