我认为模式访客的名字是相当不幸的。 而不是单词访问者,我会说Functor或Operator,而不是'访问'我会说'适用'。
我的访问者模式的理解如下:
在模板元编程(STL/BOOST)(编译时绑定),您可以从结构实现(正交设计) 操作的分离,由的函数对象手段(函子) 例如在
template <class RandomAccessIterator, class Compare>
void sort (RandomAccessIterator first, RandomAccessIterator last, Compare comp);
的补偿是代表一个非常通用的方式“小于”操作算符/运营商,所以你不必有几分许多变种功能:
对于访问者模式,您希望实现类似的功能,但在运行时(迟)绑定的情况下:
您想简化A的接口,希望保留将来扩展的可能性(新操作使用A ),并且您希望在这些扩展的情况下实现A的接口的稳定性。
从原来的“胖”类:
class A
{
public:
virtual void function_or_operation_1();//this can be implemented in terms of public interface of the other functions
virtual void function_or_operation_2();
//..etc
virtual void function_or_operation_N();
public:
//stable public interface, some functions of procedures
private:
//....
}
你从公共接口中删除尽可能多的功能(只要它们可以实现在同一个公共接口的非抽出功能方面利用由具有非常通用的接口
您减少在基类的函数数量的前进宣布Functor_or_Operator:) 和代表的操作从一个新的算符层次仿函数对象或对象
class Functor_or_Operator;
class A
{
public:
virtual void apply(Functor_or_Operator*);//some generic function operates on this objects from A hierarchy
//..etc
public:
//stable public interface, some functions
private:
//....
}
//现在在A层次结构(A,B,C)中有N(= 3)个类,而Functor_or_Operator层次结构中的类表示为M操作或函数 您需要实现N * M Functor_or_Operator的操作适用于A层次结构中的每个类。 最重要的是,你可以在不改变类'A'的接口的情况下做到这一点。 当引入新的操作或函数处理A层次对象 或A层次结构中的新派生类时,类A的声明在新增加的情况下变得非常稳定。 A的稳定性(在A不变的情况下)对于避免代价高昂(有时不可能)重新编译软件来说是很重要的,这些软件在很多地方都包含A的头文件。
对于A层次结构中的每个新类,您扩展了基础Functor_or_Operator的定义,添加新的实现文件,但是您永远不需要触及基类A的头(通常是接口类或抽象类)。
class Functor_or_Operator
{
virtual void apply(A*)=0;
virtual void apply(B*)=0;
virtual void apply(C*)=0;
}
void A::apply(Functor_or_Operator* f)
{ f->apply(this);} //you need this only if A is not abstract (it is instantiable)
class B:public A
{
public:
void apply(Functor_or_Operator* f) { f->apply(this);} //dynamic dispatch , you call polymhorphic Functor f on this object
//..the rest of B implementation.
}
class C:public A
{
public:
void apply(Functor_or_Operator* f) { f->apply(this);} //dynamic dispatch , you call polymorfic Functor f on this object
//..the rest of C implementation.
}
class Functor_or_Operator_1:public Functor_or_Operator
{
public:
//implementations of application of a function represented by Functor_or_Operator_1 on each A,B,C
void apply(A*) {}//(only if A is instantiable,not an abstract class)
void apply(B*) {}
void apply(C*) {}
}
class Functor_or_Operator_2:public Functor_or_Operator
{
public:
//implementations of application of a function represented by Functor_or_Operator_2 on each A,B,C
void apply(A*) {}//(only if A is instantiable,not an abstract class)
void apply(B*) {}
void apply(C*) {}
}
一个完整的示例,请参见Java示例中http://en.wikipedia.org/wiki/Visitor_pattern#Java_example – stefaanv 2012-04-12 07:41:40
在那个例子中,你可以很容易地使equipmentVisitor只使用功能的访问,有三个重载函数每个采用不同的派生的equipemtVisited类作为参数。只有我会让这个班级成为设备访问者。 – 2015-12-30 05:54:19