设计模式之--Visitor

该模式适用于数据结构相对稳定的系统。 它把数据结构和作用于结构上的操作之间的耦合解开,使得操作集合可以相对自由地演化。

很多系统可以按照算法和数据结构分开,如果这样的系统有比较稳定的数据结构,又有易于变化的算法的话,使用访问者模式是比较合适的,因为该模式使得算法的增加变得更加容易。 新增一种对数据的操作就是新增一种访问者。

Ref:

《大话设计模式》-- 程杰

https://www.jianshu.com/p/feec47a25b67

设计模式:visitor - 永远是学生 - 博客园

拜访者模式(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);

}

这样的话,有两个问题:

  1. Element的内部结构遍历的方法在visitor中实现,如果还有另外一个visitor要实现这个功能,它也需要实现遍历方法,这是一种重复的逻辑;
  2. 如果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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

First Snowflakes

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值