This is the 25th day of my participation in Gwen Challenge

Definition of visitor pattern

The visitor pattern is a behavioral pattern.

Encapsulates operations on elements of a data structure that define new operations on those elements without changing the data structure.

In software development, it is sometimes necessary to deal with collection object structures such as prescriptions, in which multiple types of object information are stored, and there is not a unique way of operating on elements in the same object structure, which may need to provide many different ways of handling.

Structure of the visitor pattern

The visitor pattern structure contains the following five roles:

  • Visitor: the abstract Visitor declares an access operation for each ConcreteElement class in the object structure. From the name or parameter type of the ConcreteElement, the type of the ConcreteElement to be accessed is known. The concrete Visitor implements the operation methods and defines the access operations to these elements.
  • ConcreteVisitor: Concrete visitors implement methods that abstract visitor declarations, with each operation acting on an element of a type in the structure of the access object.
  • Element: Typically an abstract class or interface that defines an Accept method, which usually takes an abstract visitor as an argument.
  • ConcreteElement: a ConcreteElement implements the Accept method, which calls the visitor’s access method to complete an element operation.
  • ObjectStructure: an ObjectStructure is a collection of elements that hold element objects and provide methods for facilitating their internal elements.

Implementation of the visitor pattern

The car is the role of the object structure, which contains the engine, body and other parts of the object. The visitor role object is PrintVisitor, the car receives the visitor to visit the various components of the car and print information.

visitor

public interface Visitor {
    void visit(Engine engine);

    void visit(Body body);

    void visit(Car car);
}
Copy the code

Visitor interface, which contains three methods

Specific visitor

Car Print Visitor:

public class PrintCar implements Visitor {
    public void visit(Engine engine) {
        System.out.println("Visiting engine");
    }

    public void visit(Body body) {
        System.out.println("Visiting body");
    }

    public void visit(Car car) {
        System.out.println("Visiting car"); }}Copy the code

Car maintenance visitors:

public class CheckCar implements Visitor {
    public void visit(Engine engine) {
        System.out.println("Check engine");
    }

    public void visit(Body body) {
        System.out.println("Check body");
    }

    public void visit(Car car) {
        System.out.println("Check car"); }}Copy the code

Abstract elements

public interface Visitable {
    void accept(Visitor visitor);
}
Copy the code

Specific elements

public class Body implements Visitable {
    @Override
    public void accept(Visitor visitor) {
        visitor.visit(this); }}Copy the code
public class Engine implements Visitable {
    @Override    
    public void accept(Visitor visitor) {
        visitor.visit(this); }}Copy the code

Object structure

public class Car {
    private List<Visitable> visit = new ArrayList<>();
    public void addVisit(Visitable visitable) {
        visit.add(visitable);
    }

    public void show(Visitor visitor) {
        for(Visitable visitable: visit) { visitable.accept(visitor); }}}Copy the code

In the example of the current visitor pattern, the list is a collection of elements (Visitable). This is a common representation of an object structure. It is usually a collection of elements, but the collection may be a tree, a linked list, or any data structure, or even several data structures. The show method, which is the essence of the car class, enumerates each element for visitors to visit.

The client

public class Client {
    static public void main(String[] args) {
        Car car = new Car();
        car.addVisit(new Body());
        car.addVisit(new Engine());

        Visitor print = newPrintCar(); car.show(print); }}Copy the code

The elements of the car are very stable and almost impossible to change, but the easiest part to change is the visitor. The biggest advantage of Visitor mode is that it is very easy to add visitors. From the code, if you want to add a Visitor, there is only one thing you need to do. The new Visitor implements the Visitor interface, and then you can call the show method of the object structure directly to access the car.

conclusion

This article mainly introduces the visitor pattern, reference wikipedia example, the author gives an implementation. As you can see from the above, the visitor pattern works well with an object structure that is stable, but you often need to define new operations on that object structure. You need to do many different, unrelated operations on objects in an object structure, and you want to avoid “contaminating” those objects’ classes, and you don’t want to modify those classes when you add new operations.

Advantages:

  • Adding new access operation is very convenient, in line with the open and close principle;
  • By centralizing the access behavior of an element object into a visitor object, rather than dividing it into element classes, the responsibilities of the classes are clearer and conform to the single responsibility principle

Main disadvantages:

  • Adding new element classes is difficult, requiring access code in each visitor class, which violates the open close principle.
  • Element objects sometimes have to expose some of their internal operations and state otherwise they cannot be accessed by visitors, breaking the element’s encapsulation.