訪問者模式(Visitor),表示一個做用於某對象結構中的各元素的操做。它使你能夠在不改變各元素的類的前提下定義做用於這些元素的新操做。ios
訪問者模式結構圖算法
訪問者模式使用與數據結構相對比較穩定的系統,即數據結構和做用與結構上的操做之間的耦合解脫開,使得操做集合能夠相對自由的演化。其目的,要把處理從數據結構分離開來。不少系統能夠按照算法和數據結構分開,若是這樣的系統有比較穩定的數據結構,又有易於變化的算法的話,使用訪問者模式就是比較合適的,由於訪問者模式使得算法操做的增長變得容易。反之,若是這樣的系統的數據結構對象易於變化,常常要有新的數據結構對象增長進來,就不適合使用訪問者模式。數據結構
訪問者模式的優勢就是增長新的操做很容易,由於增長新的操做就意味着增長一個新的訪問者。訪問者模式將有關的行爲集中到一個訪問者對象中。缺點是使增長新的數據結構變得困難了。this
其實,大多時候你並不須要訪問者模式,但當一旦須要訪問者模式時,那就是真的須要它了。spa
#include <iostream> #include <list> using namespace std; class ConcreteElementA; class ConcreteElementB; //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 { public: void VisitConcreteElementA(ConcreteElementA *concreteElementA) { cout << "ConcreteElementA被ConcreteVisitor1訪問" << endl; } void VisitConcreteElementB(ConcreteElementB *concreteElementB) { cout << "ConcreteElementB被ConcreteVisitor1訪問" << endl; } }; class ConcreteVisitor2:public Visitor { public: void VisitConcreteElementA(ConcreteElementA *concreteElementA) { cout << "ConcreteElementA被ConcreteVisitor2訪問" << endl; } void VisitConcreteElementB(ConcreteElementB *concreteElementB) { cout << "ConcreteElementB被ConcreteVisitor2訪問" << endl; } }; //Element類,定義一個Accept操做,它以一個訪問者爲參數 class Element { public: virtual void Accept(Visitor *visitor)=0; }; //ConcreteElementA和ConcreteElementB類,具體元素,實現Accept操做 class ConcreteElementA:public Element { public: //充分利用雙分派技術,實現處理與數據結構的分離 void Accept(Visitor *visitor) { visitor->VisitConcreteElementA(this); } void OperationA() { cout << "具體元素A的其餘相關方法" << endl; } }; class ConcreteElementB:public Element { public: //充分利用雙分派技術,實現處理與數據結構的分離 void Accept(Visitor *visitor) { visitor->VisitConcreteElementB(this); } void OperationA() { cout << "具體元素B的其餘相關方法" << endl; } }; //ObjectStructure類,能枚舉它的元素,能夠提供一個高層的接口以容許訪問者訪問它的元素 class ObjectStructure { private: list<Element*> m_list; public: void Attach(Element *element) { m_list.push_back(element); } void Detach(Element *element) { m_list.remove(element); } void Accept(Visitor *visitor) { list<Element*>::iterator iter; for(iter=m_list.begin();iter!=m_list.end();iter++) { if(*iter!=NULL) (*iter)->Accept(visitor); } } }; int main() { ObjectStructure *o=new ObjectStructure(); o->Attach(new ConcreteElementA()); o->Attach(new ConcreteElementB()); ConcreteVisitor1 *v1=new ConcreteVisitor1(); ConcreteVisitor2 *v2=new ConcreteVisitor2(); o->Accept(v1); o->Accept(v2); return 0; }
一般ConcreteVisitor能夠單獨開發,沒必要跟ConcreteElementA或ConcreteElementB寫在一塊兒。正由於這樣,ConcreteVisitor能提升ConcreteElement之間的獨立性,若是把一個處理動做設計成ConcreteElementA和ConcreteElementB類的方法,每次想新增「處理」以擴充功能時就得去修改ConcreteElementA和ConcreteElementB了。設計
下面是關於男人和女人的訪問者模式例子code
#include <iostream> #include <list> using namespace std; class Man; class Woman; class Action { public: virtual void GetManConclusion(Man *concreteElementA)=0; virtual void GetWomanConclusion(Woman *concreteElementB)=0; }; class Person { public: //獲取狀態對象 virtual void Accept(Action *visiton)=0; }; //這裏的關鍵在於只分爲男人和女人,這個性別的分類是穩定的,因此能夠在狀態類鎮南關,增長「男人反應」和「女人反映」兩個方法,方法個數 //是穩定的,不會很容易的發生變化。而「人」抽象類中有一個抽象方法「接受」,它是用來得到「狀態」對象的。每一種具體狀態都繼承「狀態」 //抽象類,實現兩個反應方法 class Success:public Action { public: void GetManConclusion(Man *concreteElementA) { cout << "男人成功時,背後多半有一個偉大的女人。" << endl; } void GetWomanConclusion(Woman *concretementB) { cout << "女人成功時,背後大多有一個不成功的男人。" << endl; } }; class Failing:public Action { public: void GetManConclusion(Man *concreteElementA) { cout << "男人失敗時,悶頭喝酒,誰也不用勸。" << endl; } void GetWomanConclusion(Woman *concretementB) { cout << "女人失敗時,眼淚汪汪,誰也勸不了。" << endl; } }; class Amativeness:public Action { public: void GetManConclusion(Man *concreteElementA) { cout << "男人戀愛時,凡是不懂也要裝懂。" << endl; } void GetWomanConclusion(Woman *concretementB) { cout << "女人戀愛時,遇事懂也裝做不懂。" << endl; } }; class Man:public Person { public: void Accept(Action *visitor) { visitor->GetManConclusion(this); } }; class Woman:public Person { public: void Accept(Action *visiton) { visiton->GetWomanConclusion(this); } }; //對象結構 class ObjectStructure { private: list<Person*> m_list; public: void Attach(Person *element) { m_list.push_back(element); } void Detach(Person *element) { m_list.remove(element); } void Display(Action *visitor) { list<Person*>::iterator iter=m_list.begin(); for(;iter!=m_list.end();iter++) { if(NULL!=*iter) (*iter)->Accept(visitor); } } }; int main() { ObjectStructure *o=new ObjectStructure(); o->Attach(new Man()); o->Attach(new Woman()); Success *v1=new Success(); o->Display(v1); Failing *v2=new Failing(); o->Display(v2); Amativeness *v3=new Amativeness(); o->Display(v3); return 0; }