设计模式实现(二十四)---访问者模式(Visitor)

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

我们先来看一个例子:

用面向对象的方法实现男人和女人的区别

男人这本书的内容要比封面吸引人,女人这本书的封面通常是比内容更吸引人。

男人的青春表示一种肤浅,女人的青春标志一种价值。

男人成功时,背后多半有一个伟大的女人。女人 成功时,背后大多有一个不成功的男人。

男人失败时,闷头喝酒,谁也不用劝。女人失败时,眼泪汪汪,谁也劝不了。

男人失恋时,凡事不懂也要装懂。女人恋爱时,遇事也装作不懂。

设计模式实现(二十四)---访问者模式(Visitor)_第1张图片

/*
用面向对象的方法实现男人和女人的区别
男人这本书的内容要比封面吸引人,女人这本书的封面通常是比内容更吸引人。
男人的青春表示一种肤浅,女人的青春标志一种价值。
男人成功时,背后多半有一个伟大的女人。女人 成功时,背后大多有一个不成功的男人。
男人失败时,闷头喝酒,谁也不用劝。女人失败时,眼泪汪汪,谁也劝不了。
男人失恋时,凡事不懂也要装懂。女人恋爱时,遇事也装作不懂。

*/
#include 
#include 
#include 
using namespace std;
class Action;
//抽象人类
class Person
{
public:
	virtual void Accept(Action *visitor) = 0;
public:
	string name;
};
//具体男人类
class Man: public Person
{
public:
	//首先在客户程序中将具体状态作为参数传递给‘男人’类完成第一次分派
	//然后‘男人’类调用作为参数的“具体状态”中的方法‘男人反应’,
	//同时将自己(this)作为参数传递过去。这便完成了第二次分派
	void Accept(Action *visitor);
};
//具体女人类
class Woman: public Person
{
public:
	void Accept(Action *visitor);
};
/*
这里关键就在于只分为男人和女人,这个性别的分类是稳定的,所以可以在状态类中,增加‘男人反应’和‘女人反应’两个方法,方法个数是稳定的,不会很容易的发生变化。而‘人’抽象类中有一个抽象方法‘接受’,它是用来‘获得’对象的。每一种具体状态都继承‘状态’抽象类,实现两个反应的方法。

*/
//抽象状态类
class Action
{
public:
	virtual void GetManConclusion(Man *concreteElementA) = 0;
	virtual void GetWomanConclusion(Woman *concreteElementB) = 0;
};

void Man::Accept(Action *visitor)
{
	visitor->GetManConclusion(this);
}
void Woman::Accept(Action *visitor)
{
	visitor->GetWomanConclusion(this);
}

//成功
class Success : public Action
{
public:
	void GetManConclusion(Man *concreteElementA)
	{
		cout << typeid(*concreteElementA).name() << typeid(*this).name()<<"时,背后多半有一个伟大的女人。"<elements;
public:
	void Acctach(Person *person)
	{
		elements.push_back(person);
	}
	void Detach(Person *person)
	{
		elements.remove(person);
	}
	void Display(Action *visitor)
	{
		list::iterator iter = elements.begin();
		for(;iter!=elements.end();iter++)
		{
			(*iter)->Accept(visitor);
		}
	}
};

int main()
{
	ObjectStructure o;
	Man man;
	Woman woman;
	o.Acctach(&man);
	o.Acctach(&woman);

	//成功时候的反应
	Success v1;
	o.Display(&v1);

	//失败时候的反应
	Failing v2;
	o.Display(&v2);

	return 1;
}

//这样做最大的好处就是,在我们需要增加‘结婚状态’来考察男人和女人的反应。只要增加一个‘状态’子类,就可以在客户端调用来查看,不需要修改其他代码
class Marriage : public Action
{
public:
	void GetManConclusion(Man *concreteElementA)
	{
		cout << typeid(*concreteElementA).name() << typeid(*this).name()<<"感慨道:恋爱游戏终结时,‘有妻徒刑’遥无期。"<


设计模式实现(二十四)---访问者模式(Visitor)_第2张图片

从Visitor类及上面的Action类中可以看到,访问者模式适用于相对稳定的系统,也就是它把数据结构和作用于结构上的操作之间的耦合解开,使得操作集合可以相对自由地演化,也就是Visitor可以有很多个,上面的例子中,Action可以有很多个。但是上面的ConcretePeron类只能有固定个数,有多少个,在Visitor类中就又多少个对呀的方法。

访问者模式的目的是要把处理从数据结构分离出来。很多系统可以按照算法和数据结构分开,如果这样的系统有比较稳定的数据结构,又有易于变化的算法的话,使用访问者模式就比较合适的,因为访问者模式使得算法操作的增加和改变变得容易。因为增加新的操作就意味着增加一个新的访问者。访问者模式有关的行为几种到一个访问者对象中。访问者的缺点其实也就是使增加新的数据结构变得困难了。

#include 
#include 
#include 
using namespace std;
class Visitor;
//Element类,定义一个Accept操作,它以一个访问者为参数
class Element
{
public:
	virtual void Accept(Visitor *visitor) = 0;
};
//ConcreteElementA和ConreteElementB类,具体元素,实现Accept操作。
class ConcreteElementA : public Element
{
public:
	void Accept(Visitor *visitor);
	void OperationA(){}	//其他操作方法
};
class ConcreteElementB : public Element
{
public:
	void Accept(Visitor *visitor);
	void OperationB(){}	//其他操作方法
};
//visitor类,为该对象结构中ConcreteElement的每一个类声明一个Visit操作
class Visitor
{
public:
	virtual void VisitConcreteElementA(ConcreteElementA *concreteElementA) = 0;
	virtual void VisitConcreteElementB(ConcreteElementB *concreteElementB) = 0;
};
//ConcreteVisitor1和ConcreteVisitor2类,实现每个由Visitor声明的操作。每个操作实现算法的一部分,而该算法片段乃是对应于结构中对象的类。
class ConcreteVisitor1 :public Visitor
{
	virtual void VisitConcreteElementA(ConcreteElementA *concreteElementA)
	{
		cout << typeid(*concreteElementA).name() <<"被"<< typeid(*this).name()<<"访问。"<VisitConcreteElementA(this);
}

void ConcreteElementB::Accept(Visitor *visitor)
{
	visitor->VisitConcreteElementB(this);
}


//对象结构类
class ObjectStructure
{
private:
	listelements;
public:
	void Acctach(Element *person)
	{
		elements.push_back(person);
	}
	void Detach(Element *person)
	{
		elements.remove(person);
	}
	void Display(Visitor *visitor)
	{
		list::iterator iter = elements.begin();
		for(;iter!=elements.end();iter++)
		{
			(*iter)->Accept(visitor);
		}
	}
};

int main()
{
	ObjectStructure o;
	ConcreteElementA a;;
	ConcreteElementB b;
	o.Acctach(&a);
	o.Acctach(&b);

	//成功时候的反应
	ConcreteVisitor1 v1;
	o.Display(&v1);

	//失败时候的反应
	ConcreteVisitor2 v2;
	o.Display(&v2);

	return 1;
}


你可能感兴趣的:(设计模式)