The visitor pattern (Visitor), which represents an operation that acts on elements in an object structure. It allows you to define new actions that act on these elements without changing the class of each element.
Here is a diagram of the visitor pattern:
As you can see from the class diagram, the visitor pattern is quite complicated!
The basic code structure for the visitor pattern is given below:
namespaceconsoleapplication1{//The visitor class, which declares a visit operation for each class concreteelement in the object structure. Abstract classVisitor { Public Abstract voidVisitconcreteelementa (Concreteelementa concreteelementa); Public Abstract voidvisitconcreteelementb (Concreteelementb concreteelementb); } //ConcreteVisitor1 and ConcreteVisitor2 classes, specific visitors, implement each action declared by visitor. Part of each operation implementation algorithm//the algorithm fragment is the class of the object in the corresponding structure. classConcretevisitor1:visitor { Public Override voidVisitconcreteelementa (Concreteelementa concreteelementa) {Console.WriteLine ("{0} accessed by {1}", Concreteelementa.gettype (). Name, This. GetType (). Name); } Public Override voidvisitconcreteelementb (Concreteelementb concreteelementb) {Console.WriteLine ("{0} accessed by {1}", Concreteelementb.gettype (). Name, This. GetType (). Name); } } classConcretevisitor2:visitor { Public Override voidVisitconcreteelementa (Concreteelementa concreteelementa) {Console.WriteLine ("{0} accessed by {1}", Concreteelementa.gettype (). Name, This. GetType (). Name); } Public Override voidvisitconcreteelementb (Concreteelementb concreteelementb) {Console.WriteLine ("{0} accessed by {1}", Concreteelementb.gettype (). Name, This. GetType (). Name); } } //element class, which defines a ACCEPR operation that takes a visitor as a parameter Abstract classElement { Public Abstract voidAccept (Visitor Visitor); } //Concreteelementa class and Concreteelementb class, concrete elements, implement accept class classconcreteelementa:element { Public Override voidAccept (Visitor Visitor) {Visitor. Visitconcreteelementa ( This); } Public voidOperationa () {}}classconcreteelementb:element { Public Override voidAccept (Visitor Visitor) {Visitor. VISITCONCRETEELEMENTB ( This); } Public voidoperationb () {}}//The Objectstructure class, which can enumerate its elements, can provide a high-level interface to allow visitors to access its elements classObjectstructure {Privateilist<element> elements =NewList<element>(); Public voidAttach (element Element) {elements. ADD (Element); } Public voidDetach (element Element) {elements. Remove (Element); } Public voidAccept (Visitor Visitor) {foreach(Element Einchelements) {e.accept (visitor); } } } classProgram {Static voidMain (string[] args) {objectstructure o=Newobjectstructure (); O.attach (NewConcreteelementa ()); O.attach (NewCONCRETEELEMENTB ()); ConcreteVisitor1 v1=NewConcreteVisitor1 (); ConcreteVisitor2 v2=NewConcreteVisitor2 (); O.accept (v1); O.accept (v2); Console.readkey (); } } }
The output results are as follows:
The visitor pattern is suitable for a system with relatively stable data structures, which frees up the coupling between the structure and the operation of the structure, allowing the set of operations to evolve relatively freely.
The purpose of the visitor pattern is to separate the processing from the data structure. Many systems can be separated according to the algorithm and data structure, if such a system has a relatively stable data structure, and there are easy to change the algorithm, the use of the visitor pattern is more appropriate, because the visitor pattern makes the operation of the algorithm more easy. Conversely, if such a system's data structure objects are easy to change, it is often necessary to have new data objects added in, it is not appropriate to use the visitor pattern.
A bit of the visitor pattern is that it's easy to add new operations because adding new operations means adding a new visitor. The visitor pattern concentrates the behavior on a visitor object.
The disadvantage of the visitor pattern is that it becomes difficult to add new data structures.
It is important to note that systems with relatively stable data structures are suitable for visitor patterns, such as men's and women's examples in "Big talk design mode", only men or women.
namespaceconsoleapplication1{Abstract classAction {//get a man's conclusion or reaction Public Abstract voidgetmanconclusion (man Concreteelementa); //get a woman's conclusion or reaction Public Abstract voidgetwomanconclusion (Woman concreteelementb); } Abstract classPerson {//Accept Public Abstract voidAccept (Action visitor); } //success specific "state" class classsuccess:action { Public Override voidgetmanconclusion (man Concreteelementa) {Console.WriteLine ("{0}{1}, there's probably a great woman behind it. ", Concreteelementa.gettype (). Name, This. GetType (). Name); } Public Override voidgetwomanconclusion (Woman concreteelementb) {Console.WriteLine ("{0}{1}, most of them have an unsuccessful man behind them. ", Concreteelementb.gettype (). Name, This. GetType (). Name); } } //failure specific "state" class classfailing:action { Public Override voidgetmanconclusion (man Concreteelementa) {Console.WriteLine ("{0}{1}, when drinking, no one should persuade. ", Concreteelementa.gettype (). Name, This. GetType (). Name); } Public Override voidgetwomanconclusion (Woman concreteelementb) {Console.WriteLine ("{0}{1}, tears, no one can persuade. ", Concreteelementb.gettype (). Name, This. GetType (). Name); } } //Love specific "state" class classamativeness:action { Public Override voidgetmanconclusion (man Concreteelementa) {Console.WriteLine ("{0}{1}, usually do not understand, but also to be installed to understand. ", Concreteelementa.gettype (). Name, This. GetType (). Name); } Public Override voidgetwomanconclusion (Woman concreteelementb) {Console.WriteLine ("{0}{1}, when you do not understand. ", Concreteelementb.gettype (). Name, This. GetType (). Name); } } //male Human classMan:person { Public Override voidAccept (Action visitor) {visitor. Getmanconclusion ( This);//first, the client program passes the specific state as a parameter to the "Man" class to complete a dispatch, and then the "Man" class is called as the "specific state" of the parameter.//in the method, "The man reacts", at the same time, he (this) as a parameter passed in. This completes the second dispatch. } } //female human classWoman:person { Public Override voidAccept (Action visitor) {visitor. Getwomanconclusion ( This); } } //Object Structure classObjectstructure {Privateilist<person> elements =NewList<person>(); //Increase Public voidAttach (person Element) {elements. ADD (Element); } //removed from Public voidDetach (person Element) {elements. Remove (Element); } //View Display Public voidDisplay (Action visitor) {foreach(Person Pinchelements) {p.accept (visitor); } } } classProgram {Static voidMain (string[] args) {objectstructure o=Newobjectstructure (); O.attach (NewMan ()); O.attach (NewWoman ()); //the response when successfulSuccess V1 =NewSuccess (); O.display (v1); //the reaction when it failsFailing v2 =Newfailing (); O.display (v2); //the reaction in loveAmativeness v3 =Newamativeness (); O.display (v3); Console.readkey (); } } }
The results are as follows:
What good does it do?
If you want to add a marriage status to investigate the reaction of men and women, because of the use of double allocation, just add a "state" subclass, you can use the client calls to view, no need to change any other class of code.
//Marriage Status Class classmarriage:action { Public Override voidgetmanconclusion (man Concreteelementa) {Console.WriteLine ("{0}{1}, feeling to: The end of the love game, ' have a wife sentence ' remote", Concreteelementa.gettype (). Name, This. GetType (). Name); } Public Override voidgetwomanconclusion (Woman concreteelementb) {Console.WriteLine ("{0}{1}, Happy Yue: Love long-distance running road, marriage insurance to protect the peace", Concreteelementb.gettype (). Name, This. GetType (). Name); } }
Client Add:
// Client Add New marriage (); O.display (v4);
Visitor mode-Design pattern learning