您的位置:首页 > 其它

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

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

我们先来看一个例子:

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

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

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

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

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

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



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

*/
#include <iostream>
#include <string>
#include <list>
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()<<"时,背后多半有一个伟大的女人。"<<endl;
}

void GetWomanConclusion(Woman *concreteElementB)
{
cout << typeid(*concreteElementB).name() << typeid(*this).name()<<"时,背后多半有一个不成功的男人。"<<endl;
}
};
//失败
class Failing : public Action
{
public:
void GetManConclusion(Man *concreteElementA)
{
cout << typeid(*concreteElementA).name() << typeid(*this).name()<<"时,闷头喝酒,谁也不用劝。"<<endl;
}

void GetWomanConclusion(Woman *concreteElementB)
{
cout << typeid(*concreteElementB).name() << typeid(*this).name()<<"眼泪汪汪,谁也劝不了。。"<<endl;
}
};

//对象结构类
class ObjectStructure
{
private:
list<Person *>elements;
public:
void Acctach(Person *person)
{
elements.push_back(person);
}
void Detach(Person *person)
{
elements.remove(person);
}
void Display(Action *visitor)
{
list<Person *>::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()<<"感慨道:恋爱游戏终结时,‘有妻徒刑’遥无期。"<<endl;
}

void GetWomanConclusion(Woman *concreteElementB)
{
cout << typeid(*concreteElementB).name() << typeid(*this).name()<<"欣慰曰:爱卿长跑路漫漫,婚姻保险保平安。"<<endl;
}
};

//客户端需要增加
/*
Marriage v3;
o.Display(&v3);
着完美的体现了开放-封闭原则
*/




从Visitor类及上面的Action类中可以看到,访问者模式适用于相对稳定的系统,也就是它把数据结构和作用于结构上的操作之间的耦合解开,使得操作集合可以相对自由地演化,也就是Visitor可以有很多个,上面的例子中,Action可以有很多个。但是上面的ConcretePeron类只能有固定个数,有多少个,在Visitor类中就又多少个对呀的方法。
访问者模式的目的是要把处理从数据结构分离出来。很多系统可以按照算法和数据结构分开,如果这样的系统有比较稳定的数据结构,又有易于变化的算法的话,使用访问者模式就比较合适的,因为访问者模式使得算法操作的增加和改变变得容易。因为增加新的操作就意味着增加一个新的访问者。访问者模式有关的行为几种到一个访问者对象中。访问者的缺点其实也就是使增加新的数据结构变得困难了。

#include <iostream>
#include <string>
#include <list>
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()<<"访问。"<<endl;
}
virtual void VisitConcreteElementB(ConcreteElementB *concreteElementB)
{
cout << typeid(*concreteElementB).name() <<"被"<< typeid(*this).name()<<"访问。"<<endl;
}
};
class ConcreteVisitor2 :public Visitor
{
virtual void VisitConcreteElementA(ConcreteElementA *concreteElementA)
{
cout << typeid(*concreteElementA).name() <<"被"<< typeid(*this).name()<<"访问。"<<endl;
}
virtual void VisitConcreteElementB(ConcreteElementB *concreteElementB)
{
cout << typeid(*concreteElementB).name() <<"被"<< typeid(*this).name()<<"访问。"<<endl;
}
};
//ConcreteElementA,ConcreteElementB 的 Accept方法实现
void ConcreteElementA::Accept(Visitor *visitor)
{
visitor->VisitConcreteElementA(this);
}

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

//对象结构类
class ObjectStructure
{
private:
list<Element *>elements;
public:
void Acctach(Element *person)
{
elements.push_back(person);
}
void Detach(Element *person)
{
elements.remove(person);
}
void Display(Visitor *visitor)
{
list<Element *>::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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: