在 OOP 开发中,需求变更是家常便饭。系统原型设计好之后,客户的新需求随时可能到来,最常见的应对方式是不断添加新类或新方法,结果设计越来越难以封闭,补丁打了一层又一层。

访问者模式(Visitor Pattern)的思路是:把需要变动或扩展的操作封装到一个独立的访问者类中,由被访问的元素类提供一个 Accept 接口。这样,在不改变数据结构(Element)的前提下,可以通过扩展访问者子类来添加新操作,让设计在对扩展开放的同时对修改保持封闭。

Double Dispatch

访问者模式涉及到 Double Dispatch(双分派)问题。具体调用哪一个 Accept 方法,取决于两个因素:

  1. Accept 是多态操作,需要由具体的 Element 子类决定。
  2. Accept 的参数类型是 Visitor,需要由实际的 ConcreteVisitor 来决定调用哪个 Visit 方法。

因此需要派发两次,访问者模式正是 Double Dispatch 的一种典型实现。关于 Double Dispatch 的详细阐述,可参考:http://my.oschina.net/kkkkkkkkkkkkk/blog/671305

此外,Visitor 可以为每个 Element 单独定义一个访问接口,也可以通过重载或 RTTI 来简化接口设计。

示例代码

#include "PublicHeaders.h"

#pragma once
class Visitor;


class Element
{
public:
	void Print()
	{
		cout << " this is element" << __FUNCTION__ << endl;
	}
	/**
	* @brief the interface of visitor's visit
	*/
	virtual void Accept(Visitor *visitor) = 0;
};

class Visitor
{
public:
	virtual void VisitElementA(Element*ele) = 0;

};




class ConCreateVisitor :public Visitor
{
public:

	void VisitElementA(Element *ele)
	{
		ele->Print();
	}
};

class ConCreateElementA :public Element
{
public:
	virtual void Accept(Visitor *visitor)override
	{
		visitor->VisitElementA(this);
	}
};




void testVisitor()
{
	Element *ele = new ConCreateElementA;
	Visitor *vis = new ConCreateVisitor;

	ele->Accept(vis);

}