Visitor mode
In the Visitor Pattern, we use a visitor class, which changes the execution algorithm of the element class. In this way, the execution algorithm of the element can change as the visitor changes. This type of design pattern belongs to behavioral pattern. According to the schema, the element object has accepted the visitor object so that the visitor object can handle the operations on the element object
Make.
- Visitor pattern encapsulates some operations that act on the elements of a data structure. It can define new operations that act on these elements without changing the data structure.
- It mainly separates data structure and data operation, and solves the problem of data structure and operation coupling
- The basic working principle of visitor mode is to add an interface to the visited class to provide external reception for visitors
- The main application scenarios of visitor mode are: you need to perform many different operations on objects in an object structure (these operations are not related to each other). At the same time, you need to avoid these operations "polluting" the classes of these objects. You can choose visitor mode to solve this problem
Case: Visitor mode
The audience is divided into men and women, and the singers are evaluated. After watching a singer's performance, they get different evaluations of the singer (there are different types of evaluations, such as success, failure, etc.)
public abstract class Action { //Get male evaluation public abstract void getManResult(Man man); //Get female evaluation public abstract void getWomanResult(Woman woman); }
public abstract class Person { //Provide a method that visitors can access public abstract void accept(Action action); }
public class Man extends Person { @Override public void accept(Action action) { action.getManResult(this); } }
//In the program, the double parameter is passed to the client for the first time (i.e. 1 is used as the first time) //2. Then, the Woman class calls the method getWomanResult in the "concrete method" as a parameter, and takes itself (this) as a parameter // Pass in and complete the second dispatch public class Woman extends Person{ @Override public void accept(Action action) {action.getWomanResult(this); } }
public class Success extends Action { @Override public void getManResult(Man man) { System.out.println(" The man rated the singer as successful .."); } @Override public void getWomanResult(Woman woman) {System.out.println(" The woman rated the singer as successful ..");} }
public class Fail extends Action { @Override public void getManResult(Man man) { System.out.println(" The evaluation given by the man failed the singer !"); } @Override public void getWomanResult(Woman woman) {System.out.println(" The singer failed in the evaluation given by the woman !"); } }
//Data structure, manage many people (man, woman) public class ObjectStructure { //A collection is maintained private List<Person> persons = new LinkedList<>(); //Add to list public void attach(Person p) { persons.add(p); } //remove public void detach(Person p) { persons.remove(p); } //Display evaluation status public void display(Action action) { for(Person p: persons) { p.accept(action); } } }
public class Client { public static void main(String[] args) { //Create ObjectStructure ObjectStructure objectStructure = new ObjectStructure(); objectStructure.attach(new Man()); objectStructure.attach(new Woman()); //success Success success = new Success(); objectStructure.display(success); System.out.println("==============="); Fail fail = new Fail(); objectStructure.display(fail); } }
Comply with the opening and closing principle and add a wait to be determined
public class Wait extends Action { @Override public void getManResult(Man man) {System.out.println(" The evaluation given by the man is that the singer is undetermined .."); } @Override public void getWomanResult(Woman woman) {System.out.println(" The evaluation given by the woman is that the singer is undetermined .."); } }
test
System.out.println("=======It's a pending evaluation========"); Wait wait = new Wait(); objectStructure.display(wait);
Summary - double dispatch
- Double dispatch mentioned above means that no matter how the class changes, we can find the desired method to run. Double dispatch means that the operation to be performed depends on the type of request and the type of two recipients
- Taking the above example as an example, suppose we want to add a Wait state class to investigate the response of Man class and Woman class. Due to the use of double dispatch, we only need to add an Action subclass to call on the client without changing the code of any other class.
summary
advantage
- The visitor mode conforms to the principle of single responsibility, which makes the program have excellent scalability and high flexibility
- The visitor mode can unify the functions - it can be used as reports, UI, interceptors and filters, which is suitable for systems with relatively stable data structure
shortcoming - Specific elements publish details to visitors, that is, visitors pay attention to the internal details of other classes, which is not recommended by Dimitri's law, which makes it difficult to change specific elements
- It violates the principle of inversion of dependence. Visitors rely on concrete elements, not abstract elements
- Therefore, if a system has a relatively stable data structure and frequently changing functional requirements, the visitor mode is more appropriate