Home >Java >javaTutorial >How to use Java visitor pattern to handle object structures in a beautiful way

How to use Java visitor pattern to handle object structures in a beautiful way

WBOY
WBOYforward
2023-05-09 16:01:171568browse

Introduction

Java Visitor Pattern (Visitor Pattern) is a behavioral design pattern that allows the algorithm to be separated from the objects it operates on. This pattern defines a visitor object that can access different Type of object and perform some operations, it also allows you to add new operations without modifying the existing code.

In the visitor pattern, there are two important roles: visitor and Element. An element is a component of an object structure. A visitor is an object that represents an operation to be performed. Visitors can access elements through the element's accept method.

Java visitor patterns usually involve the following 5 types Role:

  • Abstract Visitor: Defines the access method that can access each element.

  • Concrete Visitor ): Implements the access method defined by the abstract visitor, including specific operations for different elements.

  • Abstract Element (Element): Defines a method that accepts the visitor object to enable access The visitor can access himself.

  • Concrete Element: Implements the visitor method defined by the abstract element so that the visitor can access himself.

  • Object Structure: A collection containing elements that can provide an iterator to traverse the elements and can accept access from visitors.

Implementation

There are different types of animals in the zoo, including dogs, cats and birds. The visitor mode can be used to count the number of different types of animals, as well as the attribute information of different types of animals.

Abstract Elements

public interface Animal {
    void accept(Visitor visitor);
}

Concrete element

@Data
public class Bird implements Animal{
    private String name;
    private String habitat;
    public Bird(String name, String habitat) {
        this.name = name;
        this.habitat = habitat;
    }
    @Override
    public void accept(Visitor visitor) {
        visitor.visitor(this);
    }
}
@Data
public class Cat implements Animal{
    private String sound;
    private int age;
    public Cat(String sound, int age) {
        this.sound = sound;
        this.age = age;
    }
    @Override
    public void accept(Visitor visitor) {
        visitor.visitor(this);
    }
}
@Data
public class Dog implements Animal{
    private String color;
    private int size;
    public Dog(String color, int size) {
        this.color = color;
        this.size = size;
    }
    @Override
    public void accept(Visitor visitor) {
        visitor.visitor(this);
    }
}

Abstract visitor

public interface Visitor {
    void visitor(Dog dog);
    void visitor(Cat cat);
    void visitor(Bird bird);
}

Specific visitor

public class AnimalCountVisitor implements Visitor{
    private int dogCount;
    private int birdCount;
    private int catCount;
    @Override
    public void visitor(Dog dog) {
        dogCount++;
    }
    @Override
    public void visitor(Cat cat) {
        catCount++;
    }
    @Override
    public void visitor(Bird bird) {
        birdCount++;
    }
    public void printCount(){
        System.out.println("狗的个数:"+dogCount);
        System.out.println("猫的个数:"+catCount);
        System.out.println("鸟的个数:"+birdCount);
    }
}
public class AnimalFeatureVisitor implements Visitor {
    private List<String> features;
    public AnimalFeatureVisitor() {
        features = new ArrayList<>();
    }
    @Override
    public void visitor(Dog dog) {
        features.add("Dog:color=" + dog.getColor() + ",size=" + dog.getSize());
    }
    @Override
    public void visitor(Cat cat) {
        features.add("Car:sound=" + cat.getSound() + ",age=" + cat.getAge());
    }
    @Override
    public void visitor(Bird bird) {
        features.add("Bird:name=" + bird.getName() + ",habitat=" + bird.getHabitat());
    }
    public void printFeatures(){
        features.forEach(System.out::println);
    }
}

Test

public class Demo {
    public static void main(String[] args) {
        List<Animal> animals = new ArrayList<>();
        animals.add(new Dog("褐色", 50));
        animals.add(new Dog("白色", 45));
        animals.add(new Cat("喵喵叫", 2));
        animals.add(new Cat("呜呜声", 3));
        animals.add(new Bird("鹦鹉", "森林"));
        animals.add(new Bird("麻雀", "田野"));
        AnimalCountVisitor animalCountVisitor = new AnimalCountVisitor();
        AnimalFeatureVisitor animalFeatureVisitor = new AnimalFeatureVisitor();
        animals.forEach(animal -> {
            animal.accept(animalCountVisitor);
            animal.accept(animalFeatureVisitor);
        });
        animalCountVisitor.printCount();
        animalFeatureVisitor.printFeatures();
    }
}

How to use Java visitor pattern to handle object structures in a beautiful way

In this example, we have defined three animal classes, including Dog, Cat and Bird. They all implement the Animal interface and have an accept method, which passes in the Visitor type parameter.

Next, the Visitor interface is defined, which contains the visitor method, which accesses according to the different types of animals passed in.

In the specific implementation of Visitor, two visitors, AnimalCountVisitor and AnimalFeatureVisitor, are defined , the former is used to count the number of different types of animals, and the latter is used to print the attributes of different types of animals.

Summary

Advantages

  • Separate algorithms and objects: The visitor pattern makes it possible to separate algorithms and objects, because the algorithm is defined in the visitor, and the object exposes its own data to the visitor when it is accessed.

  • Good scalability: This mode can easily add new operations without affecting the existing object structure, because the visitor mode separates the object structure from the operation.

  • Conform to the open-closed principle: The visitor pattern conforms to the open-closed principle because you can add new visitors and new element types without changing existing code.

  • Simplify Code logic: The visitor pattern separates objects and operations, simplifying the code logic.

Disadvantages

  • It is difficult to add new element types : When a new element type needs to be added, the existing visitor interface must be modified, which may lead to modifications to the existing code.

  • Destruction of encapsulation: The visitor pattern requires the object to be The internal data is exposed to visitors, which may destroy the encapsulation of the object.

Application scenario

  • When a complex object structure needs to be When performing operations without exposing its internal implementation, you can use the visitor pattern.

  • When you need to add some new operations to each object in the object structure without affecting its class hierarchy When the object's class hierarchy changes, but its operation remains relatively stable, the visitor pattern can be used.

  • When you need to dynamically determine the operation to be performed at runtime, you can use the visitor pattern.

The above is the detailed content of How to use Java visitor pattern to handle object structures in a beautiful way. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:yisu.com. If there is any infringement, please contact admin@php.cn delete