One , introduction

   Let's start today “ Behavioral type ” The ninth pattern of design pattern , The mode is 【 Visitor mode 】, The English name is :Visitor
Pattern. If you follow the old rules , Let's first look at the pattern by name , I can't get any information that's useful for understanding the pattern , And this pattern is not used very much in our coding life . The intent definition of the pattern is abstract , The first time I read this definition, it's no different from no reading , Confused , In order to better understand the original intention of the model , Let's give an example to illustrate the pattern . such as : When we want to solve a new software requirement , After many days and nights of hard work , Finally through a perfect ( What I think ) The software design based on asp.net solves the new requirements of customers , And this design has a perfect class hierarchy , And it's consistent with OO Of design principles , We are very happy , I have a great sense of achievement in my design . It's been a while , The customer suddenly has a new demand , You need to add a new operation to the existing class hierarchy ( It's a way ), What should I do? ? Easy to handle , In the face of OO One of the design patterns is to solve this problem , That is “ Visitor mode ”, New operations can be easily added for classes in the existing class hierarchy , Let's move on , Take a good look at the model .

Two , Detailed introduction to visitor mode

2.1, motivation (Motivate)

  
In the process of software construction , Due to changes in demand , New behaviors often need to be added in some class hierarchies ( method ), If you make such a change directly in the base class , It will bring heavy change burden to subclasses , Even destroy the original design . How to change the class hierarchy without changing it , Transparently add new operations to each class on the class hierarchy at runtime as needed , So as to avoid the above problems ?

2.2, intention (Intent)

  
Represents an operation that acts on various elements in an object structure . It can define new operations on elements without changing their classes .                                     
——《 Design pattern 》GoF

2.3, Structure chart (Structure)

    

2.4, Composition of the model
    
    It can be seen that , In the structure diagram of visitor mode, there are the following roles :

    (1), Abstract visitor role (Vistor):
Declare one including multiple access operations , Multiple operations for multiple specific node roles ( It can be said that there are as many access operations as there are specific node roles ), Interface that all specific visitors must implement .

    (2), Specific visitor roles (ConcreteVistor): Implements all declared interfaces in the abstract visitor role , It can also be said to implement new operations for each specific node role .

    (3), Abstract node role (Element): Declare an accept operation , Accept an accessor object as a parameter , If there are other parameters , It can be here “ Accept action ” Defining the relevant parameters in .

    (4), Specific node roles (ConcreteElement): Implement the accept operation specified by the abstract element .

    (5), Structure object role (ObjectStructure): Container for node , Can contain multiple containers with different types or interfaces .

2.5, Code implementation of visitor pattern

   
Visitor pattern is not used very much in our real coding life , I'll post the code directly , Let's see the structure of the code . Today, I will give you two code examples , Let's experience the visitors . The implementation code is as follows :
1 namespace Vistor 2 { 3 // Abstract graphic definition --- amount to “ Abstract node role ”Element 4 public abstract
class Shape 5 { 6 // Draw a figure 7 public abstract void Draw(); 8 // External injection of specific visitors 9
public abstract void Accept(ShapeVisitor visitor); 10 } 11 12 // Abstract Visitor
Visitor 13 public abstract class ShapeVisitor 14 { 15 public abstract void
Visit(Rectangle shape); 16 17 public abstract void Visit(Circle shape); 18 19
public abstract void Visit(Line shape); 20 21 //
Here's one thing to say :Visit Method parameters can be written as Shape Do you ? this is it Visit(Shape
shape), Certainly. , however ShapeVisitor Subclass Visit Method needs to judge the current Shape What kind is it , yes Rectangle type , yes Circle type , Or maybe Line type .
22 } 23 24 // Specific visitors ConcreteVisitor 25 public sealed class CustomVisitor :
ShapeVisitor 26 { 27 // in the light of Rectangle object 28 public override void Visit(Rectangle
shape) 29 { 30 Console.WriteLine(" in the light of Rectangle New operation !"); 31 } 32 // in the light of Circle object
33 public override void Visit(Circle shape) 34 { 35 Console.WriteLine("
in the light of Circle New operation !"); 36 } 37 // in the light of Line object 38 public override void Visit(Line
shape) 39 { 40 Console.WriteLine(" in the light of Line New operation !"); 41 } 42 } 43 44 //
rectangle ---- amount to “ Specific node roles ” ConcreteElement 45 public sealed class Rectangle : Shape 46
{ 47 public override void Draw() 48 { 49 Console.WriteLine(" Rectangle I've drawn !"); 50
} 51 52 public override void Accept(ShapeVisitor visitor) 53 { 54
visitor.Visit(this); 55 } 56 } 57 58 // circular --- amount to “ Specific node roles ”ConcreteElement 59
public sealed class Circle : Shape 60 { 61 public override void Draw() 62 {
63 Console.WriteLine(" I've drawn the circle !"); 64 } 65 66 public override void
Accept(ShapeVisitor visitor) 67 { 68 visitor.Visit(this); 69 } 70 } 71
72 // straight line --- amount to “ Specific node roles ” ConcreteElement 73 public sealed class Line : Shape 74
{ 75 public override void Draw() 76 { 77 Console.WriteLine(" I have drawn the straight line !"); 78
} 79 80 public override void Accept(ShapeVisitor visitor) 81 { 82
visitor.Visit(this); 83 } 84 } 85 86 // Structure object role 87 internal class
AppStructure 88 { 89 private ShapeVisitor _visitor; 90 91 public
AppStructure(ShapeVisitor visitor) 92 { 93 this._visitor = visitor; 94 } 95
96 public void Process(Shape shape) 97 { 98 shape.Accept(_visitor); 99 }
100 } 101 102 class Program 103 { 104 static void Main(string[] args) 105 {
106 // If you want to perform a new operation 107 ShapeVisitor visitor = new CustomVisitor(); 108
AppStructure app =new AppStructure(visitor); 109 110 Shape shape = new
Rectangle();111 shape.Draw();// Perform your own actions 112 app.Process(shape);// Perform new actions 113 114
115 shape = new Circle(); 116 shape.Draw();// Perform your own actions 117 app.Process(shape);//
Perform new actions 118 119 120 shape = new Line(); 121 shape.Draw();// Perform your own actions 122
app.Process(shape);// Perform new actions 123 124 125 Console.ReadLine(); 126 } 127 } 128 }
This is the second code instance of visitor mode :
1 namespace Visitor 2 { 3 // Abstract visitor role Visitor 4 public abstract class Visitor
5 { 6 public abstract void PutTelevision(Television tv); 7 8 public
abstract void PutComputer(Computer comp); 9 } 10 11 // Specific visitor roles
ConcreteVisitor 12 public sealed class SizeVisitor : Visitor 13 { 14 public
override void PutTelevision(Television tv) 15 { 16 Console.WriteLine("
By product size {0} discharge ", tv.Size); 17 } 18 19 public override void PutComputer(Computer
comp) 20 { 21 Console.WriteLine(" By product size {0} discharge ", comp.Size); 22 } 23 } 24
25 // Specific visitor roles ConcreteVisitor 26 public sealed class StateVisitor : Visitor 27
{ 28 public override void PutTelevision(Television tv) 29 { 30
Console.WriteLine(" By old and new value of goods {0} discharge ", tv.State); 31 } 32 33 public override void
PutComputer(Computer comp) 34 { 35 Console.WriteLine(" By old and new value of goods {0} discharge ",
comp.State); 36 } 37 } 38 39 // Abstract node role Element 40 public abstract class
Goods 41 { 42 public abstract void Operate(Visitor visitor); 43 44 private
int nSize; 45 public int Size 46 { 47 get { return nSize; } 48 set { nSize
= value; } 49 } 50 51 private int nState; 52 public int State 53 { 54
get { return nState; } 55 set { nState = value; } 56 } 57 } 58 59 //
Specific node roles ConcreteElement 60 public sealed class Television : Goods 61 { 62
public override void Operate(Visitor visitor) 63 { 64 visitor.PutTelevision(
this); 65 } 66 } 67 68 // Specific node roles ConcreteElement 69 public sealed class
Computer : Goods 70 { 71 public override void Operate(Visitor visitor) 72 {
73 visitor.PutComputer(this); 74 } 75 } 76 77 // Structure object role 78 public sealed
class StoragePlatform 79 { 80 private IList<Goods> list = new List<Goods>();
81 82 public void Attach(Goods element) 83 { 84 list.Add(element); 85 }
86 87 public void Detach(Goods element) 88 { 89 list.Remove(element); 90
} 91 92 public void Operate(Visitor visitor) 93 { 94 foreach (Goods g in
list) 95 { 96 g.Operate(visitor); 97 } 98 } 99 } 100 101 class Program
102 { 103 static void Main(string[] args) 104 { 105 StoragePlatform platform =
new StoragePlatform(); 106 platform.Attach(new Television()); 107
platform.Attach(new Computer()); 108 109 SizeVisitor sizeVisitor = new
SizeVisitor();110 StateVisitor stateVisitor = new StateVisitor(); 111 112
platform.Operate(sizeVisitor);113 platform.Operate(stateVisitor); 114 115
Console.Read();116 } 117 } 118 }

Three , The implementation of visitor pattern :

    Visitor Through the so-called dual distribution (double
dispatch) Come on, don't change now Element Under the premise of class hierarchy , Transparently add new operations to each class in the class hierarchy at runtime . The so-called double distribution is Visitor Two polymorphic distributions are included in the pattern ( Pay attention to the mechanism of polymorphism ): The first is accept Analysis of the polymorphism of methods ; The second is visit Analysis of the polymorphism of methods .


   Design pattern is actually a way to close the loopholes , But no design pattern can close all the holes , It's the same even when you combine design patterns . Every design pattern has flaws , There are situations or changes that they can't solve . Each design pattern assumes a change , It's assumed that there's some kind of immutability .Visitor The pattern assumes that the operation changes , and Element Class hierarchy is stable .

    (1), The main advantages of the visitor model are :

       
1】, Visitor mode makes it easy to add new operations . If some operations depend on a complex structural object , So in general , Adding new operations can be complex . Use visitor mode , Adding a new action means adding a new visitor class . therefore , Make it easy to add new operations .

        2】, Visitor mode enables related behavior operations to be concentrated in one visitor object , Instead of dispersing into element classes . This is similar to ” Intermediary model ”.

        3】, Visitor pattern can access member objects belonging to different hierarchies , Iteration can only access member objects belonging to the same hierarchy .

 (2), The main disadvantages of visitor mode are :

       
1】, Adding new element classes becomes difficult . Adding a new element means adding a new abstract operation to the abstract visitor role , And add corresponding specific operations to each specific visitor class . say concretely ,Visitor The biggest disadvantage of schema is to extend the class hierarchy ( Add new Element Subclass ), Will lead to Visitor Class changes . therefore Visitor Mode applies to “Element Class hierarchy is stable , But the operation often faces frequent changes ”.

    (3), Consider using the visitor pattern in the following situations :

        1】, If the system has a relatively stable data structure , When there are algorithms that are easy to change , Consider using the visitor pattern at this point . Because the visitor mode makes it easy to add algorithm operations .

        2】, If a group of classes , There are similar operations , To avoid a lot of duplicate code , Consider encapsulating repetitive actions into visitors .( Of course, you can also consider using abstract classes )

        3】, If there are some objects that are not related to their own objects , Or operation with weak relationship , To avoid contamination of this object by operation , Consider encapsulating these operations into the visitor object .


Four ,.NET Implementation of visitor pattern

    
In today's Net Inside the frame , If you want to add a new method to an existing class , There's a new way , That is “ Extension method ”, It is the same as the instance method , And in Net Inside the frame , Microsoft has also written many extension methods for us to use . I haven't learned yet Net The framework class library of “ Visitor mode ” realization , It seems that I still need to work hard , The revolution is not yet successful .

Five , summary

   
Visitor mode is finished , It's a very difficult model to understand at the beginning , however , If we look at a few more instance codes , Complete mastery is not a problem . along with C# The development of language , A lot of things in design patterns , We can go through C# Some features of language make a better alternative . We need to write design patterns slowly at the beginning , Write the code step by step , When we master the core meaning of the model , We're going to write a match C# Pattern code for styles and features , Or we need to use C# To write design patterns , The code will be better .