Visitor mode
1 Definition
Encapsulates some operations that act on each element in a data structure. It can define new operations that act on these elements without changing the data structure.
2 Structure
The visitor pattern contains the following main roles:
- Abstract visitor role: defines the behavior of accessing each element. Its parameters are the accessible elements. Theoretically, the number of methods is the same as the number of element classes. 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 role: give the specific behavior generated when accessing each element class
- Abstract element role: defines a method to accept visitors. Its meaning means that every element can be accessed by visitors
- Specific element role: provide the 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 role: the object structure mentioned in the definition. The object structure is an abstract expression. Specifically, it can be understood as a class with container nature or object characteristics. It will contain a group of elements, and these elements can be iterated for visitors to access
3 Implementation
Feeding pets: now there are many people who have pets. Let's take this as an example. Of course, pets are also divided into dogs, cats, etc. if you want to feed pets, the owner can feed them, and others can feed them.
- Abstract visitor role: the person who feeds the pet
- Specific visitor roles: host, others
- Abstract element character: Animal abstract class
- Specific element roles: pet dog, pet cat
- Structure object role: master home
//Abstract visitor role public interface Person { //Feed the cat void feed(Cat cat); //feed a dog void feed(Dog dog); }
//Abstract element role public interface Animal { //Accept functions accessed by designated visitors void accept(Person person); }
//Specific element character (CAT) public class Cat implements Animal{ @Override public void accept(Person person) { person.feed(this); System.out.println("Kittens eat food"); } }
//Specific element role (dog) public class Dog implements Animal{ @Override public void accept(Person person) { person.feed(this); System.out.println("Dogs eat food"); } }
//Specific visitor role (host) public class Owner implements Person{ @Override public void feed(Cat cat) { System.out.println("The owner feeds the cat"); } @Override public void feed(Dog dog) { System.out.println("The owner feeds the dog"); } }
//Specific visitor roles (others) public class Someone implements Person{ @Override public void feed(Cat cat) { System.out.println("Others feed the cat"); } @Override public void feed(Dog dog) { System.out.println("Other feeding dogs"); } }
//Object structure role public class Home { //Declare a collection object to store elements private List<Animal> animals = new ArrayList<>(); //Add element public void add(Animal animal){ animals.add(animal); } public void action(Person person){ //Traverse the collection, get each element, and let visitors access each element for (Animal animal : animals) { animal.accept(person); } } }
//Test class public class Test { public static void main(String[] args) { //Create home object Home home = new Home(); //Add element home.add(new Dog()); home.add(new Cat()); //Create master Owner owner = new Owner(); //Let the host feed home.action(owner); } }
Test results:
The owner feeds the dog
Dogs eat food
The owner feeds the cat
Kittens eat food
4 advantages and disadvantages
advantage:
- Good expansibility: add new functions to the elements in the object structure without modifying the elements in the object structure
- Good reusability: define the general functions of the whole object structure through visitors, so as to improve the degree of reusability
- Separate irrelevant behaviors: separate irrelevant behaviors through visitors, and encapsulate relevant behaviors to form a visitor, so that each visitor has a single function
Disadvantages:
- It is difficult to change the object structure: in the visitor mode, each new element class is added with corresponding specific operations in each specific visitor, which violates the "opening and closing principle"
- Violating the dependency inversion principle: the visitor pattern relies on concrete classes instead of abstract classes
5 usage scenarios
- The object structure is relatively stable, but its operation algorithm often changes
- The objects in the object structure need to provide a variety of different and irrelevant operations, and the changes of these operations should not affect the structure of the object