Java Design Pattern Series (two or three) visitor mode (vistor)

Source: Internet
Author: User

Java Design Pattern Series (two or three) visitor mode (vistor)

The visitor pattern is the behavior pattern of the object. The purpose of the visitor pattern is to encapsulate some operations that are applied to a data structure element. Once these operations need to be modified, the data structure that accepts the operation can remain intact.

First, the visitor pattern structure

The visitor pattern is suitable for systems with relatively indeterminate data structures, which frees up the coupling between the structure and the operation of the structure, allowing the set of operations to evolve relatively freely.

Each node of the data structure can accept a call from a visitor that passes in the node object to the visitor object, while the visitor object performs the operation of the node object in turn. Such a process is called "double allocation". The node invokes the visitor, passes it on itself, and the visitor executes an algorithm against the node. The schematic class diagram for the visitor pattern is as follows:

The visitor pattern involves the following roles:

    • Abstract visitor (Visitor) role: Declares one or more method actions that form the interface that all specific visitor roles must implement.

    • Specific visitor (Concretevisitor) role: Implements the interface declared by the abstract visitor, which is the individual access actions declared by the abstract visitor.

    • Abstract node role: declares an accept operation that accepts a visitor object as a parameter.

    • Specific node (Concretenode) Role: Implements the accepted operation specified by the abstract node.

    • struct object (objectstructure) role: It is the responsibility to traverse all elements of the structure and, if required, provide a high-level interface that allows the visitor object to access each element, or, if necessary, a composite object or a aggregation, such as a List or Set.

Source

(1) Vistor

As you can see, the abstract visitor role prepares an access operation for each specific node. Since there are two nodes, there are two access operations for the corresponding one.

 Public InterfaceVisitor {/** corresponds to the access operation of the NodeA * /     Public void Visit(NodeA node);/** corresponds to the access operation of the NodeB * /     Public void Visit(NodeB node);} Public classVisitoraImplementsVisitor {/** corresponds to the access operation of the NodeA * /    @Override     Public void Visit(NodeA node) {System. out.println(node.Operationa()); }/** corresponds to the access operation of the NodeB * /    @Override     Public void Visit(NodeB node) {System. out.println(node.operationb()); }} Public classVisitorbImplementsVisitor {/** corresponds to the access operation of the NodeA * /    @Override     Public void Visit(NodeA node) {System. out.println(node.Operationa()); }/** corresponds to the access operation of the NodeB * /    @Override     Public void Visit(NodeB node) {System. out.println(node.operationb()); }}

(2) Node

 Public Abstract classNode {/** Accept Operation * /     Public Abstract void Accept(Visitor Visitor);} Public classNodeAextendsnode{/** Accept Operation * /    @Override     Public void Accept(Visitor Visitor) {Visitor.Visit( This); }/** NodeA Unique method * /     PublicStringOperationa(){return "NodeA"; }} Public classNodeBextendsnode{/** Acceptance Method * /    @Override     Public void Accept(Visitor Visitor) {Visitor.Visit( This); }/** NodeB Unique method * /     PublicStringoperationb(){return "NodeB"; }}

(3) Objectstructure

publicclass ObjectStructure {    privatenew ArrayList<Node>();    /** 执行方法操作 */    publicvoidaction(Visitor visitor) {        for(Node node : nodes) {            node.accept(visitor);        }    }    /** 添加一个新元素 */    publicvoidadd(Node node){        nodes.add(node);    }}

(4) test

publicclass Client {    publicstaticvoidmain(String[] args) {        //创建一个结构对象        newObjectStructure();        //给结构增加一个节点        os.add(newNodeA());        //给结构增加一个节点        os.add(newNodeB());        //创建一个访问者        newVisitorA();        os.action(visitor);    }}
Ii. Concept of distribution

The type of the variable being declared is called the static type of the variable, and some people call the static type the explicit type (apparent type), whereas the real type of the object referenced by the variable is called the actual type of the variable (Actual type). Like what:

nullnew ArrayList();

Declares a list of variables, its static type (also known as the obvious type) is list, and its actual type is ArrayList.

The choice of the method according to the type of the object is the allocation (Dispatch), and the allocation (Dispatch) is divided into two kinds, namely static dispatch and dynamic dispatch.

    1. Static allocation (static Dispatch) occurs at compile time, and allocations occur based on static type information. Static dispatch is no stranger to us, and method overloading is static dispatch.

    2. Dynamic Dispatch (Dispatch) occurs at run time, and dynamic dispatch dynamically displaces a method.

(1) Static dispatch

Java supports static dispatch through method overloading.

 Public classMozi { Public void Ride(Horse h) {System. out.println("Horseback Riding"); } Public void Ride(Whitehorse WH) {System. out.println("Riding a white Horse"); } Public void Ride(Blackhorse BH) {System. out.println("Riding a black Horse"); } Public Static void Main(string[] args) {Horse WH =New Whitehorse(); Horse BH =New Blackhorse(); Mozi Mozi =New Mozi(); Mozi.Ride(WH); Mozi.Ride(BH); }}

Obviously, the ride () method of the Mozi class is made up of three method overloads. These three methods accept the parameters of Horse (Horse), White Horse (Whitehorse), Black Horse (Blackhorse) and so on respectively.

So at run time, what will the program print out? The result is that the program prints the same two lines of "riding". In other words, Mozi found that all he rode was horses.

Why is it? Two calls to the ride () method pass in different parameters, that is, WH and BH. Although they have different true types, their static types are the same, all of which are Horse types.

The dispatch of an overloaded method is based on a static type, and the dispatch process is completed at compile time.

(2) Dynamic dispatch

Java supports dynamic dispatch through rewriting of methods.

 Public classHorse { Public void Eat() {System. out.println("The Horse Eats the Grass"); }} Public classBlackhorseextendsHorse {@Override     Public void Eat() {System. out.println("Dark Horse eats Grass"); }} Public classClient { Public Static void Main(string[] args) {Horse h =New Blackhorse(); H.Eat(); }}

The static type of the variable h is Horse, and the real type is blackhorse. If the Eat () method of the last line above calls the Eat () method of the Blackhorse class, then the print is "dark horse grazing"; Conversely, if the Eat () method above calls the Horse () method of the Eat class, then the print is "horse grazing".

So, at the heart of the problem is that the Java compiler does not always know which code will be executed at compile time, because the compiler knows only the static type of the object, not the actual type of the object, and the invocation of the method is based on the actual type of the object, not the static type. In this way, the Eat () method of the last line above calls the Eat () method of the Blackhorse class, which prints "dark horse grazing".

(3) Type of assignment

The object that a method belongs to is called the receiver of the method, and the method's receiver and the method's parameters are collectively known as the method's volume. Like the test class in the example below

publicclass Test {    publicvoidprint(String str){        System.out.println(str);    }}

In the above class, the print () method belongs to the test object, so its receiver is the test object. The print () method has one parameter, str, and its type is String.

The object-oriented language can be divided into single-Dispatch languages (Uni-dispatch) and multi-Dispatch languages (Multi-dispatch), depending on how many kinds of parcels can be allocated. The single-Dispatch language chooses the method based on the type of a volume, and the multi-Dispatch language chooses the method based on the type of the more than one volume.

Both C + + and Java are single-Dispatch languages, and examples of multi-tasking languages include CLOS and Cecil. According to this distinction, Java is a dynamic single-dispatch language, because the dynamic allocation of the language only takes into account the type of receiver of the method, but also the static multi-Dispatch language, because the assignment of overloaded methods in this language takes into account the type of receiver of the method and the type of all parameters of the method.

In a language that supports dynamic single dispatch, there are two conditions that determine which action a request will invoke: The first is the name of the request, but the actual type of the receiver. A single dispatch restricts the process of selecting a method so that only one volume can be taken into account, which is usually the recipient of the method. In the Java language, if an operation is acting on an object of unknown type, then the real type test of the object will only happen once, which is the characteristic of the dynamic single dispatch.

(4) Double allocation

One method determines the execution of different code based on the type of two parcels, which is "dual allocation." The Java language does not support dynamic multi-tasking, which means that Java does not support dynamic dual dispatch. However, by using design patterns, dynamic double allocations can also be implemented in the Java language.

In Java, two method calls can be used to achieve the purpose of two allocations.

Iii. Summary (1) Advantages and disadvantages of visitor pattern

Advantages of the visitor pattern

    • Good extensibility: The ability to add new functionality to elements in an object structure without modifying the elements in the object structure.

    • Good reusability: You can improve the reusability by defining the functions common to the entire object structure through the visitor.

    • Detach unrelated behavior: You can separate unrelated behaviors by the visitor, encapsulate related behaviors together, and form a visitor, so that each visitor's function is relatively single.

Disadvantages of the visitor pattern

    • It is difficult to change the structure of an object: it does not apply to situations in which classes in the object structure change frequently, because the structure of the object changes, and the visitor's interface and the visitor's implementation change accordingly, at a high cost.

    • Break encapsulation: Visitor patterns often require an object structure to open internal data to visitors and Objectstructrue, which destroys the encapsulation of objects.

Record a little bit every day. Content may not be important, but habits are important!

Java Design Pattern Series (two or three) visitor mode (vistor)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.