Visitor pattern (behavioral pattern)

9. Visitor pattern

visitor pattern (Vistor Pattern) is a design pattern that separates data structure and data manipulation. It refers to encapsulating some operations that act on various elements in a certain data structure, and it can define new operations that act on these elements without changing the data structure.

The basic idea of ​​the visitor pattern is to provide an accept() method to accept the visit of the visitor object for certain fixed types of object structures (elements) in the system. Different visitors have different access contents to the same element, so the same element can produce different element results. That is to say, different visitors access different properties in the same object, resulting in different results.

9.1 Composition structure

  • Abstract visitor (Visitor) role: defines the behavior of visiting each element (Element). Its parameters are the elements that can be accessed. The number of its methods is theoretically related to the number of element classes (the number of implementation classes of Element) ) is the same. From this point, it is not difficult to see that the visitor pattern requires that the number of element classes cannot be changed.
  • Specific visitor (ConcreteVisitor) role: gives the specific behavior that occurs when visiting each element class.
  • Abstract element (Element) role: defines a method (accept) to accept visitors, which means that each element must be accessible by visitors.
  • Concrete Element (ConcreteElement) role: Provide a specific implementation of the access method, and this specific implementation usually uses the method provided by the visitor to access the element class.
  • Object structure (Object Structure) role: the object structure mentioned in the definition, the object structure is an abstract expression, the specific point can be understood as a class with container properties or composite object characteristics, it will contain a set of elements (Element), And these elements can be iterated for visitors to visit.

9.2 Scene Design

For example, the company’s year-end summary, the company’s CEO and CTO want to see the project status of the year. Here, employees are divided into ordinary employees and project managers. The CEO cares about the employee’s kpi and the number of projects, while the CEO cares about the employee’s kpi and the number of completed projects. The CTO cares about the amount of employee code and the number of completed projects. (This does not mean that different visitors have different access content to the same fixed element, resulting in different results)

9.3 Implementation

abstract visitor

public interface Visitor {

    //visit staff
    void visit(Engineer engineer);

    //access manager
    void visit(Manager manager);
}

specific visitor

//ceo
public class CEOVisitor implements Visitor{

    @Override
    public void visit(Engineer engineer) {
        System.out.println("ceo visiting engineer");

        System.out.println("engineer:" + engineer.getName() + "KPI:" + engineer.getKpi());
    }

    @Override
    public void visit(Manager manager) {
        System.out.println("ceo interview manager");
        System.out.println("manager:" + manager.getName() + "KPI:" + manager.getKpi() + " Projects completed this year:" + manager.getProductNum() + "indivual");
    }
}

//cto
public class CTOVisitor implements Visitor{
    @Override
    public void visit(Engineer engineer) {
        System.out.println("cto visiting engineer");
        System.out.println("engineer:" + engineer.getName() + " This year's code volume" + engineer.getCodeLineTotal() + "Row");
    }
    @Override
    public void visit(Manager manager) {
        System.out.println("cto access manager");
        System.out.println("manager:" + manager.getName() + "KPI:" + manager.getKpi() + " Projects completed this year:" + manager.getProductNum() + "indivual");
    }
}

abstract interviewee

public interface Employee {

    //How employees are accessed
    void accept(Visitor visitor);
}

specific interviewee

//Engineer Object Interviewed
public class Engineer  implements Employee{

    private String name;

    private int kpi;

    Engineer(String name){
        this.name = name;
        this.kpi = new Random().nextInt(10);
    }
    @Override
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }

    public int getCodeLineTotal(){
        return this.kpi * 1000000;
    }
}

//manager object, visitor
public class Manager implements Employee{
    private String name;

    private int kpi;

    Manager(String name){
        this.name = name;
        this.kpi = new Random().nextInt(10);
    }
    @Override
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }

    public int getProductNum(){
        return this.kpi * 10;
    }
}

structure object

public class EmployeeStructure {

    List<Employee> list = new ArrayList<>();

    public EmployeeStructure addEmployee(Employee employee){
        list.add(employee);
        return this;
    }
    public void report(Visitor visitor){
        list.forEach(employee -> {
            employee.accept(visitor);
        });
    }
}

test class

public class Client {
    public static void main(String[] args) {
        EmployeeStructure structure = new EmployeeStructure();
        Engineer engineerZ = new Engineer("Xiao Zhang");
        Engineer engineerW = new Engineer("Xiao Wang");
        Engineer engineerL = new Engineer("Xiao Li");

        Manager managerZ = new Manager("boss Zhang");
        Manager managerW = new Manager("Mr. Wang");
        Manager managerL = new Manager("President Li");

        structure.addEmployee(engineerZ);
        structure.addEmployee(engineerW);
        structure.addEmployee(engineerL);

        structure.addEmployee(managerZ);
        structure.addEmployee(managerW);
        structure.addEmployee(managerL);
        //structure.report(new CEOVisitor());
        structure.report(new CTOVisitor());
    }
}

9.4 Advantages and disadvantages

advantage:

  • Good scalability

    Add new functionality to elements in an object structure without modifying the elements in the object structure.

  • Good reusability

    The visitor is used to define functions common to the entire object structure, thereby increasing the degree of reuse.

  • Separation of irrelevant behavior

    Use visitors to separate irrelevant behaviors, and encapsulate related behaviors to form a visitor, so that the function of each visitor is relatively single.

shortcoming:

  • Object structure changes are difficult

    In the visitor mode, every time a new element class is added, corresponding specific operations must be added to each specific visitor class, which violates the "opening and closing principle".

  • Violates the Dependency Inversion Principle

    The visitor pattern relies on concrete classes, not abstract classes.

9.5 Usage Scenarios

  • A program whose object structure is relatively stable, but whose operation algorithm changes frequently.

  • The objects in the object structure need to provide many different and unrelated operations, and the changes of these operations should not affect the structure of the object.

Posted by sonoton345 on Thu, 17 Nov 2022 10:51:02 +1030