策略,访客和模板方法之间的区别是什么?

时间:2010-11-24 12:28:43

标签: design-patterns strategy-pattern visitor template-method-pattern

我正在上课,我们刚刚了解了这些设计模式。但是我看不出它们之间有什么区别。它们听起来像是一样的,在抽象的类上创建具体的类。有人可以帮我解决这个疑问吗?谢谢(:

2 个答案:

答案 0 :(得分:24)

访问者,策略和模板模式都包含算法的应用。最大的区别在于它们是如何被唤起的以及它们在实践中的使用方式。虽然看起来它们具有相同的用例,但请查看对象的构造以查看差异。

当我们无法将函数作为第一类对象传递时,通常会使用策略模式。它需要一个非常具体的参数列表,并且只能在其调用模式中使用该参数列表。例如:

struct MyStrat{
    void operator()(const Foo &_input){
        _input.up( 2 );
    }
};

std::for_each( myFooList.begin(), myFooList.end(), MyStrat() );

然后应用于“Foo”类型的对象列表。我们真的没有办法将它应用于任何其他对象。

另一方面,当我们想要将算法应用于可能不共享相同签名但也没有相同成员函数的一堆对象时,使用访问者模式。我们说访问者模式,因为它经常在遍​​历树或其他“无关”对象集合时使用(在继承意义上无关。)

struct MyVisitor{
    void visit(const Foo &_input){
         _input.up( 2 );
    }
    void visit(const Bar &_input){
         _input.raiseUp( 2 );
    }
    void visit(const Baz &_input){
         _input.setUp( 2 );
    }
 };

这里的想法是我们想要“升级”所有这些对象。它们都不共享相同的成员函数签名,但都与概念相关。因此,我们可以“访问”这些类中的每一个,但期望算法执行相同类型的任务。

通过使用访问者模式,我们避免了在代理模式中包装每个类的需要。因此,对于N个类,我们想要应用此算法,我们不需要生成N个代理类。我们只需要向访问者类添加N个方法。

模板方法与访问者和策略模式完全不同。使用模板您要尝试执行的操作是强制执行相同类型的算法,但是在层次结构中的不同子类上。例如:

class Duck{
public:
    int count() =0;
    void makeNoise(int times) =0;
    void quack(){ makeNoise( count() ); }//the template pattern is here
};

class Mallard : public Duck{
public:
    int count(){ return 4; }
    void makeNoise( cout << "quack" << endl; }
};

class Daffy{
public:
    int count(){ return 1; }
    void makeNoise( cout << "Why I ought to..." << endl; }
};

因此算法的结果在层次结构中变化。

答案 1 :(得分:1)

共性:

  1. 策略,模板方法和访问者:所有三种模式都归类为行为模式。
  2. 差异:

    1. 模板方法使用继承,策略使用合成
    2. 不应覆盖基类实现的模板方法这样,算法的结构由超类控制,细节在子类中实现
    3. 策略将算法封装在界面后面,这使我们能够在运行时更改算法
    4. 访问者模式用于对一组类似的对象执行操作。借助访问者模式,我们可以将操作逻辑从对象移动到另一个类
    5. 如果操作的实施发生变化,我们只需更改访客类,而不是触及所有其他对象。
    6. 查看Template methodStrategyVisitor以及Sourcemaking文章,以便更好地理解。

      相关帖子:

      When should I use the Visitor Design Pattern?

      Real World Example of the Strategy Pattern

      Template design pattern in JDK, could not find a method defining set of methods to be executed in order