14. Visitor visitor mode

Encapsulate some operations that act on each element in a certain data structure. It can define new operations that act on these elements without changing the data structure.

Class Diagram

Code example

The visitor pattern is probably the most complicated one of the behavioral patterns.

1.	class A {  
2.	    public void method1(){  
3.	        System.out.println("我是A");  
4.	    }  
5.	      
6.	    public void method2(B b){  
7.	        b.showA(this);  
8.	    }  
9.	}  
10.	  
11.	class B {  
12.	    public void showA(A a){  
13.	        a.method1();  
14.	    }  
15.	}  

We mainly look at the difference between method1 and method2 in class A. Method1 is very simple, just print out a sentence "I am A"; method2 is a little more complicated, using class B as a parameter and calling the class B's showA method. Let's look at the showA method of class B. The showA method uses class A as a parameter, and then calls the method1 method of class A. You can see that the method2 method goes around, it is nothing more than calling its own method1 method, and it runs The result should also be "I am A". After the analysis, let's run these two methods and see the results:

 

1.	public class Test {  
2.	    public static void main(String[] args){  
3.	        A a = new A();  
4.	        a.method1();  
5.	        a.method2(new B());  
6.	    }  
7.	}  

The running result is:

I am A
I am A

After reading this example, you can understand 90% of the visitor pattern. In the example, for class A, class B is a visitor. But this example is not all of the visitor pattern. Although it is intuitive, its scalability is relatively poor. Let's talk about the general implementation of the visitor pattern. You can see through the class diagram that in the visitor pattern, the main Including the following roles:

  1. Abstract visitor: Abstract class or interface, which declares which elements the visitor can visit. Specifically, the parameters in the visit method define which objects can be visited in the program.
  2. Visitor: Implement the method declared by the abstract visitor, which affects what the visitor should do after visiting a class.
  3. Abstract element class: interface or abstract class, which declares which type of visitor is allowed to access, which is defined programmatically through the parameters in the accept method. Abstract elements generally have two types of methods, one of which is their own business logic, and the other is which types of visitors are allowed to access.
  4. Element class: implement the accept method declared by the abstract element class, usually visitor.visit(this), which has basically formed a fixed formula.
  5. Structural object: A container of elements, which generally contains a container of multiple different classes and different interfaces, such as List, Set, Map, etc. Generally, this role is rarely abstracted in projects.

General code implementation of visitor pattern:

1.	abstract class Element {  
2.	    public abstract void accept(IVisitor visitor);  
3.	    public abstract void doSomething();  
4.	}  
5.	  
6.	interface IVisitor {  
7.	    public void visit(ConcreteElement1 el1);  
8.	    public void visit(ConcreteElement2 el2);  
9.	}  
10.	  
11.	class ConcreteElement1 extends Element {  
12.	    public void doSomething(){  
13.	        System.out.println("这是元素1");  
14.	    }  
15.	      
16.	    public void accept(IVisitor visitor) {  
17.	        visitor.visit(this);  
18.	    }  
19.	}
20.	class ConcreteElement2 extends Element {  
21.	    public void doSomething(){  
22.	        System.out.println("这是元素2");  
23.	    }  
24.	      
25.	    public void accept(IVisitor visitor) {  
26.	        visitor.visit(this);  
27.	    }  
28.	}  
29.	class Visitor implements IVisitor {  
30.	  
31.	    public void visit(ConcreteElement1 el1) {  
32.	        el1.doSomething();  
33.	    }  
34.	      
35.	    public void visit(ConcreteElement2 el2) {  
36.	        el2.doSomething();  
37.	    }  
38.	}  
39.	class ObjectStruture {  
40.	    public static List<Element> getList(){  
41.	        List<Element> list = new ArrayList<Element>();  
42.	        Random ran = new Random();  
43.	        for(int i=0; i<10; i++){  
44.	            int a = ran.nextInt(100);  
45.	            if(a>50){  
46.	                list.add(new ConcreteElement1());  
47.	            }else{  
48.	                list.add(new ConcreteElement2());  
49.	            }  
50.	        }  
51.	        return list;  
52.	    }  
53.	}  
54.	  
55.	public class Client {  
56.	    public static void main(String[] args){  
57.	        List<Element> list = ObjectStruture.getList();  
58.	        for(Element e: list){  
59.	            e.accept(new Visitor());  
60.	        }  
61.	    }  
62.	}  

Advantages and disadvantages of visitor mode

  1. Compliance with the principle of single responsibility: in any scenario where the visitor model is applied, the operations in the element class that need to be encapsulated in the visitor must be operations that have little to do with the element class itself and are volatile. Using the visitor model on the one hand conforms to the single responsibility Principles, on the other hand, because the encapsulated operations are usually changeable, when changes occur, the extension of the changed part can be achieved without changing the element class itself.
  2. Good scalability: Element classes can be extended to different operations by accepting different visitors.

Visitor mode usage scenarios

If there are some operations that are irrelevant (or weakly related) to the object in an object, in order to avoid these operations from polluting the object, you can use the visitor pattern to encapsulate these operations into the visitor.

If there are similar operations in a group of objects, in order to avoid a large number of repeated codes, these repeated operations can also be encapsulated in the visitor.

However, the visitor model is not so perfect, it also has a fatal flaw: it is difficult to add new element classes. Through the code of the visitor pattern, we can see that in the visitor class, each element class has its corresponding processing method, that is to say, each additional element class needs to modify the visitor class (including the visitor class Subclass or implementation class), it is quite troublesome to modify. In other words, the visitor mode should be used with caution when the number of element classes is uncertain. Therefore, the visitor model is more suitable for the reconstruction of existing functions. For example, the basic function of a project has been determined, and the data of the element type has been basically determined and will not change. What will change is only the correlation within these elements. Operation, at this time, we can use the visitor mode to refactor the original code, so that we can modify the original function without modifying each element class.

 

Guess you like

Origin blog.csdn.net/sinat_37138973/article/details/88636394