Visitor(访问者)设计模式

声明:本博文篇幅短,适合review。

一、概念

       访问者模式就是表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。

二、模式结构图


class Visitor
{
public:
	virtual ~Visitor();
	virtual void VisitConcreteElementA(Element* elm) = 0;
	virtual void VisitConcreteElementB(Element* elm) = 0;
};

class ConcreteVisitorA : public Visitor {
public:
	ConcreteVisitorA();
	~ConcreteVisitorA();
	void visitConcreteElementA(Element* elm){
		cout<<"ConcreteVisitorA Visit A"<<endl;	
	}
	void visitConcreteElementB(Element* elm){
		cout<<"ConcreteVisitorA Visit B"<<endl;
	}
};

class ConcreteVisitorB : public Visitor {
public:
	ConcreteVisitorB();
	~ConcreteVisitorB();
	void visitConcreteElementA(Element* elm){
		cout<<"ConcreteVisitorB Visit A"<<endl;
	}
	void visitConcreteElementB(Element* elm){
		cout<<"ConcreteVisitorB Visit B"<<endl;
	}
};

class Element
{
public:
	virtual ~Element();
	virtual void accept(Visitor* vis) = 0;
};

class ConcreteElementA : public Element {
public:
	ConcreteElementA();
	~ConcreteElementA();
	void accept(Visitor* vis){
		vis->visitConcreteElementA(this);
	}
};

class ConcreteElementB : public Element {
public:
	ConcreteElementB();
	~ConcreteElementB();
	void accept(Visitor* vis){
		vis->visitConcreteElementB(this);
	}
};

class ObjectStructure{
public:
	void attach(Element * e){
		mVec.push_back(e);
	}
	void detach(Element * e){
		mVec.remove(e);
	}
	void accept(Visitor * v){
		for (list<Element *>::iterator it = mVec.begin(); it != mVec.end(); it++){
			(*it)->accept(v);
		}
	}
private:
        list<Element *> mVec;
};

void main(){
	ObjectStructure * ob = new ObjectStructure();
	ob->attach(new ConcreteElementA());
	ob->attach(new ConcreteElementB());
	
	Visitor * visA = new ConcreteVisitorA();
	Visitor * visB = new ConcreteVisitorB();
	
	ob->accept(visA);
	ob->accept(visB);
}

三、例子

class Business
{
public:
	virtual ~Business();
	virtual void doBySpcl(SellWindow* sw) = 0;
	virtual void doByNml(SellWindow* sw) = 0;
};

class Buy : public Business {
public:
	void doBySpcl(SellWindow* sw){
		cout<<"Buy Special ticket "<<endl;	
	}
	void doByNml(SellWindow* sw){
		cout<<"Buy Normal ticket"<<endl;
	}
};

class Change : public Business {
public:
	void doBySpcl(SellWindow* sw){
		cout<<"Change Special ticket"<<endl;
	}
	void doByNml(SellWindow* sw){
		cout<<"Change Normal ticket"<<endl;
	}
};

class SellWindow
{
public:
	virtual ~SellWindow();
	virtual void doBusiness(Business* bs) = 0;
};

class SpecialWindow : public SellWindow {
public:
	void doBusiness(Business* bs){
		bs->doBySpcl(this);
	}
};

class NormalWindow : public SellWindow {
public:
	void doBusiness(Business* bs){
		bs->doByNml(this);
	}
};

class SellHall{
public:
	void attach(SellWindow * sw){
		mVec.push_back(sw);
	}
	void detach(SellWindow * sw){
		mVec.remove(sw);
	}
	void doBusiness(Business * bs){
		for (list<SellWindow *>::iterator it = mVec.begin(); it != mVec.end(); it++){
			(*it)->doBusiness(bs);
		}
	}
private:
	list<SellWindow *> mVec;
};

void main(){
	SellHall * sh = new SellHall();
	sh->attach(new SpecialWindow());
	sh->attach(new NormalWindow());
	
	Buy * by = new Buy();
	Change * cg = new Change();
	
	sh->doBusiness(by);
	sh->doBusiness(cg);
}

四、优缺点

       1、优点

             a、增加新的Visitor变得很容易,满足开闭原则。

             b、访问者模式将有关的行为集中到一个Visitor对象中,而不是分散到一个个的Element中。

             c、访问者模式可以跨过几个类的等级结构访问属于不同的等级结构的成员类。迭代子只能访问属于同一个类型等级结构的成员对象,而不能访问属于不同等级结构的对象。访问者模式可以做到这一点。

       2、缺点

             a、不方便增加新的Element。

             b、Visitor的访问暴露了Element的操作和状态,破坏了封装。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值