该模式适用于数据结构相对稳定的系统。 它把数据结构和作用于结构上的操作之间的耦合解开,使得操作集合可以相对自由地演化。
很多系统可以按照算法和数据结构分开,如果这样的系统有比较稳定的数据结构,又有易于变化的算法的话,使用访问者模式是比较合适的,因为该模式使得算法的增加变得更加容易。 新增一种对数据的操作就是新增一种访问者。
Ref:
《大话设计模式》-- 程杰
https://www.jianshu.com/p/feec47a25b67
拜访者模式(visitor)适用于对复杂结构体进行解析的场景。
所谓复杂结构体,是指包含多个子元素的对象,比如集合,树,图,或者组合对象……。结构体中的每个元素,包括结构体本身实现接口:
Element{
//element的信息属性,在此省略
//专门用于调用visitor的方法
void accept(visitor)
}
所谓解析,是指提取结构体中各个元素的相关信息,组合起来。解析器实现接口:
Visitor{
void accept(Element的具体子类);//因为不同的Element子类有不同的信息
}
对于client来说,按照如下模式调用:
visitor= new XXXVisitor;
Element e=从外界获得的实例;
e.accept( visitor )
visitor.getOutput();
-----------
为什么需要Visitor模式呢?
让我们考虑这样的情形,结构体是一个二叉树的结构体,如果不用visitor模式,那么Visitor的visit方法定义如下:
void visit( Element root){
if(root != null)
accept(root);
if(root.right!=null) visit(root.right);
if(root.left!=null) visit(root.left);
}
这样的话,有两个问题:
- Element的内部结构遍历的方法在visitor中实现,如果还有另外一个visitor要实现这个功能,它也需要实现遍历方法,这是一种重复的逻辑;
- 如果element的内部结构调整了,visitor1 和visitor2都必须改变。
所以visitor模式就是采用参观者和被参观对象的角色变换,实现了结构体和解析逻辑的解耦合。他适用于对同一个结构体有多种解析方法的情形。
--------------------------------------------------------
An example, use different visitor to traverse a binary tree. One visitor is used to get the sum of all nodes, the other node is used to get the product of all nodes:
struct Node {
Node(int a = 0) {
val = a;
left = nullptr;
right = nullptr;
}
int val = 0;
Node* left = nullptr;
Node* right = nullptr;
};
class visitorBase {
public:
virtual void solve(Node* node) = 0;
};
class visitorAdd: public visitorBase {
public:
int result = 0;
void solve(Node* node) {
result += node->val;
}
};
class visitorMultiply : public visitorBase {
public:
int result = 1;
void solve(Node* node) {
result *= (node->val);
}
};
class binaTree {
public:
void accept(visitorBase& visitor) {
if (!root) {
return;
}
std::stack<Node*> Cache;
Cache.push(root);
while (!Cache.empty()) {
Node* currNode = Cache.top();
Cache.pop();
visitor.solve(currNode); //
if (currNode->left) {
Cache.push(currNode->left);
}
if (currNode->right) {
Cache.push(currNode->right);
}
}
}
void setTree(Node* node) {
root = node;
}
private:
Node* root = nullptr;
};
int main()
{
Node* root = new Node(1);
root->left = new Node(2);
root->right = new Node(5);
binaTree biTreeObj;
biTreeObj.setTree(root);
visitorAdd addVisitor;
biTreeObj.accept(addVisitor);
std::cout << "addVisitor = " << addVisitor.result << std::endl; // 8
visitorMultiply mulVisitor;
biTreeObj.accept(mulVisitor);
std::cout << "mulVisitor = " << mulVisitor.result << std::endl; // 10
return 0;
}