First, a primer
For a completed class hierarchy in the system, we have provided it with an interface to meet the requirements. But what should we do in the face of new increases in demand? If this is a few changes, and you don't have to change the entire class hierarchy in order to adjust to a requirement, it might be a good idea to modify the original class hierarchy directly.
But often we are confronted with the possibility that such changes in demand may continue to occur and, more importantly, that any change in demand may require you to change the entire class hierarchy to the bottom. This kind of operation is distributed among different classes, which is not a good phenomenon, so we have to refactor this structure.
Well, the visitor pattern may be a good choice for you.
II. Definition and structure
The visitor pattern, as the name suggests, uses this pattern to be able to improve the existing code functionality by adding additional "visitors" without modifying the existing program structure.
Design pattern is defined by the visitor pattern as representing an operation that acts on the elements of an object structure. It allows you to define new operations that act on these elements without changing the classes of each element. From the definition you can see that the structure object is necessary to use the visitor pattern, and that the struct object must have a way of traversing its own objects. This is similar to the collection concept in Java.
The following is the composition structure of the visitor pattern:
1) Visitor Role (Visitor): Declares an access operation interface for the specific element role in the object structure. The name and parameters of the operation interface identify the specific element roles that send access requests to specific audiences. This allows the visitor to access it directly through the specific interface of the element role.
2 The specific visitor role (concrete Visitor): Implements each action declared by the visitor role (Visitor).
3 element role: Defines a accept operation, which takes a visitor as an argument.
4 The specific element role (concrete Element): Implements the accept operation provided by the element role.
5 Object structure role (object Structure): This is the role that is required to use the visitor pattern. It has the following characteristics: it can enumerate its elements; it can provide a high-level interface to allow the visitor to access its elements; it can be a composite (combination pattern) or a collection, such as a list or an unordered set.
You can see the structure of the visitor pattern more clearly by drawing a class diagram.
So like the introduction of the hypothetical. What should we do to make the visitor model run? First we add the Accept method to the original class hierarchy. The classes in this class hierarchy are then put into an object structure. This will create the visitor role ...
Iii. examples
I have not been able to find examples of visitor patterns in practical applications. I had to borrow the instructional code from thinking in Patterns with Java. I did a little modification.
import java.util.*;
import junit.framework.*;
//Visitor role
interface Visitor {
void Visit (Gladiolus g);
void Visit (Runuculus R);
void Visit (chrysanthemum c);
}
//The Flower hierarchy cannot be changed:
//Element role
interface Flower {
void Accept (Visitor v);
}
//below three specific element roles
class Gladiolus implements Flower {
public void Accept (Visitor v) {v.visit (this);}
}
class Runuculus implements Flower {
public void Accept (Visitor v) {v.visit (this);}
}
class Chrysanthemum implements Flower {
public void Accept (Visitor v) {v.visit (this);}
}
//ADD the ability to produce a string:
//Implementation specific visitor role
class Stringval implements Visitor {
String S;
public String toString () {return s;}
public void Visit (Gladiolus g) {
s = "Gladiolus";
}
public void Visit (Runuculus r) {
s = "Runuculus";
}
public void visit (Chrysanthemum c) {
s = "chrysanthemum";
}
}
//ADD The ability to do "Bee" Activities:
//Another specific visitor role
class Bee implements Visitor {
public void Visit (Gladiolus g) {
System.out.println ("Bee and Gladiolus");
}
public void Visit (Runuculus r) {
System.out.println ("Bee and Runuculus");
}
public void visit (Chrysanthemum c) {
System.out.println ("Bee and Chrysanthemum");
}
}
//This is an object builder
//This is not a complete object structure, this is just an element in the simulation object structure
class Flowergenerator {
private static Random rand = new Random ();
public static Flower Newflower () {
Switch (Rand.nextint (3)) {
Default:
Case 0:return New Gladiolus ();
Case 1:return New Runuculus ();
Case 2:return new Chrysanthemum ();
}
}
}
//Customer test procedures
public class Beeandflowers extends TestCase {
/*
Here you can see the flow of visitor mode execution:
first get a specific visitor role on the client
Traversal Object Structure
calls the Accept method on each element to pass the specific visitor role into the
This completes the whole process
*/
//object structure roles are assembled here
List flowers = new ArrayList ();
public beeandflowers () {
for (int i = 0; i < i++)
Flowers.add (Flowergenerator.newflower ());
}
Visitor Sval;
public void Test () {
//It ' s almost as if I had a function to
//produce a Flower string representation:
//This place you can modify to use another specific visitor role
sval = new Stringval ();
Iterator it = Flowers.iterator ();
while (It.hasnext ()) {
((Flower) It.next ()). Accept (Sval);
System.out.println (Sval);
}
}
public static void Main (String args[]) {
Junit.textui.TestRunner.run (Beeandflowers.class);
}
}