访问者模式
理论
访问者模式(Visitor),表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。
访问者模式的目的:
把处理从数据结构分离出来。把数据结构和作用于结构上的操作之间的耦合解脱开,使得操作集合可以相对自由地演化。
访问者模式的优点:
使增加新的操作变得容易,因为增加新的操作就意味着增加一个新的访问者。访问者模式将有关的行为集中到一个访问者对象中。
访问者模式的缺点:
使增加新的数据结构变得困难。
访问者模式的应用场景:
系统有比较稳定的数据结构,又有易于变化的算法,使用访问者模式可以把算法和数据结构分开,使得算法操作的增加变得容易。
实例
男人和女人在成功、失败、恋爱、结婚时的状态不一样:
男人成功时,背后多半有一个伟大的女人。
女人成功时,背后大多有一个不成功的男人。
男人失败时,闷头喝酒,谁也不用劝。
女人失败时,眼泪汪汪,谁也劝不了。
男人恋爱时,凡是不懂也要装懂。
女人恋爱时,遇事懂也装作不懂。
男人结婚时,感慨道: 恋爱游戏终结时,‘有妻徒刑’遥无期。
女人结婚时,欣慰道: 爱情长跑路漫漫,婚姻保险保平安。
UML类图
代码实现
#include <iostream> #include <list> using namespace std; class Man; class Woman; //状态的抽象类 class Action { public: virtual void GetManConclusion(Man* concreteElementA) {} virtual void GetWomanConclusion(Woman* concreteElementB) {} }; //人的抽象类 class Person { public: virtual void Accept(Action* visitor) {} }; //男人类 class Man :public Person { public: void Accept(Action* visitor) { visitor->GetManConclusion(this); } string GetName() { return name; } private: string name = "男人"; }; //女人类 class Woman :public Person { public: void Accept(Action* visitor) { visitor->GetWomanConclusion(this); } string GetName() { return name; } private: string name = "女人"; }; //具体状态类 //成功 class Success :public Action { public: void GetManConclusion(Man* concreteElementA) { cout << concreteElementA->GetName() << this->action << "时,背后多半有一个伟大的女人。" << endl; } void GetWomanConclusion(Woman* concreteElementB) { cout << concreteElementB->GetName() << this->action << "时,背后大多有一个不成功的男人。" << endl; } private: string action = "成功"; }; //失败 class Failing :public Action { public: void GetManConclusion(Man* concreteElementA) { cout << concreteElementA->GetName() << this->action << "时,闷头喝酒,谁也不用劝。" << endl; } void GetWomanConclusion(Woman* concreteElementB) { cout << concreteElementB->GetName() << this->action << "时,眼泪汪汪,谁也劝不了。" << endl; } private: string action = "失败"; }; //恋爱 class Amativeness :public Action { public: void GetManConclusion(Man* concreteElementA) { cout << concreteElementA->GetName() << this->action << "时,凡是不懂也要装懂。" << endl; } void GetWomanConclusion(Woman* concreteElementB) { cout << concreteElementB->GetName() << this->action << "时,遇事懂也装作不懂。" << endl; } private: string action = "恋爱"; }; //扩展结婚状态类 class Marriage :public Action { public: void GetManConclusion(Man* concreteElementA) { cout << concreteElementA->GetName() << this->action << "时,感慨道: 恋爱游戏终结时,‘有妻徒刑’遥无期。" << endl; } void GetWomanConclusion(Woman* concreteElementB) { cout << concreteElementB->GetName() << this->action << "时,欣慰道: 爱情长跑路漫漫,婚姻保险保平安。" << endl; } private: string action = "结婚"; }; //对象结构 class ObjectStructure { public: void Attach(Person* element) { elements.push_back(element); } void Detach(Person* element) { elements.remove(element); } void Display(Action* visitor) { for (Person* e : elements) { e->Accept(visitor); } } private: list<Person*> elements; }; int main() { ObjectStructure* os = new ObjectStructure(); os->Attach(new Man()); os->Attach(new Woman()); Action* v1 = new Success(); os->Display(v1); Action* v2 = new Failing(); os->Display(v2); Action* v3 = new Amativeness(); os->Display(v3); //扩展结婚状态 Action* v4 = new Marriage(); os->Display(v4); delete v4; delete v3; delete v2; delete v1; return 0; }
运行结果: