Design pattern (twenty-four) visitor pattern

Visitor Pattern

1. What is the visitor pattern

Visitor Pattern: Provides an operation representation that acts on each element in an object structure. It allows us to define new operations that act on these elements without changing the class of each element.
The visitor pattern is an object behavior pattern.

How to provide multiple different operation modes for elements in the same collection object? The visitor model is a solution worth considering, it can solve the above problems to a certain extent (solve most of the problems). The visitor mode can provide multiple access operations for different types of elements, and can add new operations without modifying the original system.

The visitor pattern includes two main components: visitor and visited element. These visited elements usually have different types, and different visitors can perform different visit operations on them. The visitor mode allows users to expand the functions of the system without modifying the existing system, adding new operations to these different types of elements.

When there is a more complex object structure in the system, and different visitors take different operations on it, consider using the visitor pattern for design.

2. Role analysis of visitor pattern

Structure diagram of visitor mode:
Visitor mode

  • Vistor (abstract visitor): The abstract visitor declares an access operation for each concrete element class ConcreteElement in the object structure. From the name or parameter type of this operation, you can clearly know the type of specific element that needs to be accessed. The specific visitor needs to implement these Operation method, which defines the access operation to these elements.
  • ConcreteVisitor (concrete visitor): The concrete visitor implements each operation declared by the abstract visitor, and each operation is used to access a type of element in the object structure.
  • Element (abstract element): Abstract elements are generally abstract classes or interfaces, which define an accept() method, which usually takes an abstract visitor as a parameter.
  • ConcreteElement (concrete element): The concrete element implements the accept() method. In the accept() method, the visitor's access method is called to complete the operation of an element.
  • ObjectStructure (object structure): Object structure is a collection of elements, it is used to store element objects, and provides methods to traverse its internal elements. It can be implemented in combination with a combination mode, or it can be a simple collection object, such as a List object or a Set object.

The object structure in the visitor pattern stores different types of element objects for different visitors to access.
The visitor pattern includes two hierarchical structures:

  1. One is the visitor hierarchy, which provides abstract visitors and specific visitors,
  2. One is the element hierarchy, which provides abstract and concrete elements.
    The same visitor can access different elements in different ways, and the same element can be accessed by different visitors in different ways.
    In the visitor mode, adding new visitors does not need to modify the original system, and the system has good scalability.
  • Abstract visitors define methods for accessing element objects, and usually provide an access method for each type of element object, and specific visitors can implement these access methods.
    These access methods are generally named in two ways: one is to directly indicate the specific type of the element object to be accessed in the method name, such as visitElementA (ElementA elementA), and the other is to uniformly name visit() and pass the parameter type To define a series of overloaded visit() methods. Of course, if all visitors have the same access operation to a certain type of element, the operation code can be moved to the abstract visitor class. The typical code is as follows:
abstract class Visitor {
    
    
	public abstract void visit(ConcreteElementA elementA);
	public abstract void visit(ConcreteElementB elementB);
	public void visit(ConcreteElementC elementC) {
    
    
		//元素ConcreteElementC操作代码
	}
}
  • For the element class, an accept() method is generally defined in it to accept visitor access
interface Element {
    
    
	public void accept(Visitor visitor);
}

This method passes in a parameter of the abstract visitor type, that is, programming for the abstract visitor, not the specific visitor. The type of the specific visitor is determined when the program is running, and the visit() of the specific visitor object is called Methods implement operations on element objects.
The accept() method is implemented in the subclass of the abstract element class Element to accept visits from visitors. In the specific element class, you can also define business methods specific to different types of elements. The typical code is as follows:

class ConcreteElementA implements Element {
    
    
	public void accept(Visitor visitor) {
    
    
		visitor.visit(this);
	}
	
	public void operationA() {
    
    
		//业务方法
	}
}
  • The object structure is a collection, which is used to store element objects and accept visitor access. The typical code is as follows:
class ObjectStructure{
    
    
	private ArrayList<Element> list = new ArrayList<Element>(); //定义一个集合用于存储元素对象
 
	public void accept(Visitor visitor) {
    
    
		Iterator i=list.iterator();
		while(i.hasNext()) {
    
    
			((Element)i.next()).accept(visitor); //遍历访问集合中的每一个元素
		}
	}
 
	public void addElement(Element element){
    
    
		list.add(element);
	}
 
	public void removeElement(Element element){
    
    
		list.remove(element);
	}

3. Advantages and disadvantages of visitor mode

advantage:

  • It is very convenient to add new access operations. Using the visitor mode, adding a new visit operation means adding a new specific visitor class, which is simple to implement, does not need to modify the source code, and conforms to the "open and close principle".
  • Concentrate the access behaviors of related element objects into one visitor object instead of being scattered in individual element classes. The responsibilities of the class are clearer, which is conducive to the reuse of element objects in the object structure. The same object structure can be accessed by multiple different visitors.
  • Allows users to define operations that act on the hierarchy without modifying the existing element class hierarchy.

Disadvantages:

  • It is difficult to add new element classes. In the visitor pattern, every new element class added means that a new abstract operation is added to the abstract visitor role, and a corresponding specific operation is added to each specific visitor class, which violates the "open "Closed principle".
  • Destroy the package. The visitor model requires the visitor object to access and call the operation of each element object, which means that the element object must sometimes expose some of its own internal operations and internal state, otherwise it cannot be accessed by the visitor.

Applicable scene:

  • An object structure contains multiple types of objects, and it is hoped to perform some operations that depend on their specific types on these objects. An access operation is provided for each specific type among visitors, and different types of objects can have different access operations.
  • It is necessary to perform many different and unrelated operations on the objects in an object structure, and it is necessary to avoid allowing these operations to "contaminate" the classes of these objects, and it is not desirable to modify these classes when adding new operations. The visitor pattern allows us to centralize related visit operations and define them in visitor classes. The object structure can be used by multiple different visitor classes, separating the object itself from the access operations of the object.
  • The class corresponding to the object in the object structure rarely changes, but it is often necessary to define new operations on the object structure.

4. Practical impression

The visitor model splits two levels to organize classes, one is the visitor hierarchy and the other is the element hierarchy.
The operation provided is: the
same visitor can access different elements, so these different elements must be in a collection, the visitor to traverse the visit, that is, the ObjectStructure class; the
same element can be accessed by different visitors . In the implementation, the visitor can be passed in the element method parameter, which is the Vistor class;

5. Code example

// 元素类
interface Employee {
    
    
    //接受一个抽象访问者访问
    void accept(Department handler); 
}

class FulltimeEmployee implements Employee {
    
    
    private String name;

    FulltimeEmployee(String name) {
    
    
        this.name = name;
    }

    @Override
    public void accept(Department handler) {
    
    
        //调用访问者的访问方法
        handler.visit(this);
    }
}

class ParttimeEmployee implements Employee {
    
    
    private String name;

    ParttimeEmployee(String name) {
    
    
        this.name = name;
    }

    @Override
    public void accept(Department handler) {
    
    
        //调用访问者的访问方法
        handler.visit(this);
    }
}

// 访问者类
abstract class Department {
    
    
    abstract void visit(FulltimeEmployee employee);
    abstract void visit(ParttimeEmployee employee);
}

// 财务部门访问者
class FADepartment extends Department {
    
    
    //实现财务部对全职员工的访问
    @Override
    public void visit(FulltimeEmployee employee) {
    
    
        System.out.println("财务部门访问全职员工的逻辑");
    }

    //实现财务部对兼职员工的访问
    @Override
    public void visit(ParttimeEmployee employee) {
    
    
        System.out.println("财务部门访问兼职员工的逻辑");
    }
}

// 元素集合类
class HRDepartment extends Department {
    
    
    //实现人力资源部对全职员工的访问
    @Override
    public void visit(FulltimeEmployee employee) {
    
    
        System.out.println("人力部门访问全职员工的逻辑");
    }

    //实现人力资源部对兼职员工的访问
    @Override
    public void visit(ParttimeEmployee employee) {
    
    
        System.out.println("人力部门访问兼职员工的逻辑");
    }
}

class EmployeeList {
    
    
    //定义一个集合用于存储员工对象
    private ArrayList<Employee> list = new ArrayList<Employee>();

    void addEmployee(Employee employee) {
    
    
        list.add(employee);
    }

    //访问者遍历访问元素
    void accept(Department handler) {
    
    
        for (Object obj : list) {
    
    
            ((Employee) obj).accept(handler);
        }
    }
}

    public static void main(String[] args) {
    
    
        EmployeeList list = new EmployeeList();
        Employee fte1, fte2, fte3, pte1, pte2;

        fte1 = new FulltimeEmployee("1");
        fte2 = new FulltimeEmployee("2");
        fte3 = new FulltimeEmployee("3");
        pte1 = new ParttimeEmployee("4");
        pte2 = new ParttimeEmployee("5");

        list.addEmployee(fte1);
        list.addEmployee(fte2);
        list.addEmployee(fte3);
        list.addEmployee(pte1);
        list.addEmployee(pte2);

        //  财务部门访问所有员工
        Department dep = new FADepartment();
        list.accept(dep);
    }

Guess you like

Origin blog.csdn.net/u014099894/article/details/85219137
Recommended