行为型模式之访问者模式(Visitor)

1. 意图
表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。
2. 动机

考虑一个编译器,它将源程序表示为一个抽象语法树。该编译器需在抽象语法树上实施某些操作以进行“静态语义”分析,例如检查是否所有的变量都已经被定义了。它也需要生成代码。因此它可能要定义许多操作以进行类型检查、代码优化、流程分析,检查变量是否在使用前被赋初值,等等。此外,还可使用抽象语法树进行优美格式打印、程序重构、c o d ei n s t r u m e n t a t i o n以及对程序进行多种度量。

3.结构


• Vi s i t o r(访问者,如N o d e Vi s i t o r)
— 为该对象结构中C o n c r e t e E l e m e n t的每一个类声明一个Vi s i t操作。该操作的名字和特征标识了发送Vi s i t请求给该访问者的那个类。这使得访问者可以确定正被访问元素的具体的类。这样访问者就可以通过该元素的特定接口直接访问它。
• C o n c r e t e Vi s i t o r(具体访问者,如Ty p e C h e c k i n g Vi s i t o r)
— 实现每个由Vi s i t o r声明的操作。每个操作实现本算法的一部分,而该算法片断乃是对应于结构中对象的类。C o n c r e t e Vi s i t o r为该算法提供了上下文并存储它的局部状态。这一状态常常在遍历该结构的过程中累积结果。
• E l e m e n t(元素,如N o d e)
— 定义一个A c c e p t操作,它以一个访问者为参数。
• C o n c r e t e E l e m e n t(具体元素,如A s s i g n m e n t N o d e,Va r i a b l e R e f N o d e)
— 实现A c c e p t操作,该操作以一个访问者为参数。
• O b j e c t S t r u c t u r e(对象结构,如P r o g r a m)
— 能枚举它的元素。
— 可以提供一个高层的接口以允许该访问者访问它的元素。
— 可以是一个复合(参见C o m p o s i t e(4 . 3))或是一个集合,如一个列表或一个无序集合。

4.举例

#ifndef VISITOR_H
#define VISITOR_H
#include <iostream>
#include <string>
#include <list>
using std::cout;
using std::endl;
using std::string;
using std::list;
class Element;
class Visitor{
public:
	virtual void Visit(Element* tmp){} 
};
class Element{
public:
	virtual void Accept(Visitor* tmp){}
};
class Worker : public Element{
private:
	string name;
	int salary;
	int vocation;
public:
	Worker(string nam,int sal,int voc):name(nam),salary(sal),vocation(voc){}
	virtual void Accept(Visitor* tmp){
		tmp->Visit(this);
	}
	string GetName(){return name;}
	int GetSalary(){return salary;}
	int GetVocation(){return vocation;}
	void SetSalary(int value){salary+=value;}
	void SetVocation(int data){vocation+=data;}
	void Show(){
		cout<<GetName()<<":  ";
		cout<<GetSalary()<<"  ";
		cout<<GetVocation()<<endl;
	}
};
class SalaryVistor : public Visitor{
public:
	virtual void Visit(Element* tmp){
		Worker* pWorker=(Worker*)tmp;
		pWorker->Show();
		pWorker->SetSalary(1000);		
		pWorker->Show();
	}
};
class VocationVistor : public Visitor{
public:
	virtual void Visit(Element* tmp){
		Worker* pWorker=(Worker*)tmp;
		pWorker->Show();
		pWorker->SetVocation(1);		
		pWorker->Show();
	}
};
class Boss{
private:
	list<Element* > pool;
public:
	void Attach(Element* tmp){
		pool.push_back(tmp);
	}
	void Detach(Element* tmp){
		pool.remove(tmp);
	}
	void Accept(Visitor* tmp){
		for(list<Element* >::iterator it=pool.begin();it!=pool.end();it++){
			(*it)->Accept(tmp);
		}
	}
};
#endif


#include "visitor.h"
int main(){
	Element* pEleA=new Worker("James",10000,1);
	Element* pEleB=new Worker("Kobe",12000,2);
	Element* pEleC=new Worker("Wade",13000,3);
	Boss Nba;
	Nba.Attach(pEleA);
	Nba.Attach(pEleB);
	Nba.Attach(pEleC);
	Visitor* pVisA=new SalaryVistor;
	Visitor* pVisB=new VocationVistor;
	Nba.Accept(pVisA);
	Nba.Accept(pVisB);
	delete pEleA;
	delete pEleB;
	delete pEleC;
	delete pVisA;
	delete pVisB;
	return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值