我正在上课,我们刚刚了解了这些设计模式。但是我看不出它们之间有什么区别。它们听起来像是一样的,在抽象的类上创建具体的类。有人可以帮我解决这个疑问吗?谢谢(:
答案 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)
共性:
差异:
查看Template method,Strategy和Visitor以及Sourcemaking文章,以便更好地理解。
相关帖子:
When should I use the Visitor Design Pattern?