Java and mode 26-24th-Visitor Mode

Source: Internet
Author: User
Document directory
  • Source code
  • Source code
  • Preparation Process sequence diagram
  • Access process sequence diagram

The visitor mode is the behavior mode of objects. The visitor mode aims to encapsulate operations that are applied to certain data structure elements. Once these operations need to be modified, the data structure that accepts the operation can remain unchanged.

Assignment Concept

  When a variable is declared, the type is called the static type of the variable. Some people call the static type apparent type ); the actual type of the object referenced by the variable is also called the actual type of the variable (actual type ). For example

List list = null;list = new ArrayList();

 

Declares a variable list. Its static type (also called explicit type) is list, and its actual type is arraylist.

The method selected based on the object type is the dispatch (dispatch), which is divided into two types:Static assignmentAndDynamic Allocation.

  Static dispatch)Occurs during the compilation period, and the assignment occurs based on static type information. Static distribution is no stranger to us. Method overloading means static distribution.

  Dynamic dispatch)In the running period, a method is dynamically assigned and replaced.

Static assignment

JAVA supports static allocation through method overloading. The story of Mozi riding is used as an example. Mozi can ride a white horse or a dark horse. The Mozi and Whitehorse, dark horse, and horse classes are shown as follows:

 

In this system, Mozi is represented by the Mozi class.

Package COM. bankht. visitor;/*** @ Author: -AK47 * @ Creation Time: 10:41:24 ** @ Class description: In this system, mozi is represented by the Mozi class */public class Mozi {public void ride (horse H) {system. out. println ("horse riding");} public void ride (Whitehorse Wh) {system. out. println ("Riding White Horse");} public void ride (Blackhorse BH) {system. out. println ("");} public static void main (string [] ARGs) {Horse wh = new Whitehorse (); horse bH = new Blackhorse (); mozi = new Mozi (); Mozi. ride (Wh); Mozi. ride (BH );}}

 

Obviously, the ride () method of the Mozi class is composed of three methods that are overloaded. These three methods accept parameters of the following types: Horse (Horse), White Horse (Whitehorse), and black horse (Blackhorse.

So what results will the program print at runtime? The result is that the program prints the same two "horse riding" lines ". In other words, Mozi finds that he is riding a horse.

Why? The two calls to the ride () method pass in different parameters, that is, WH and BH. Although they have different real types, their static types are the same, all of which are horse types.

The assignment of the overload method is based on the static type, and the assignment process is completed during compilation.

Dynamic Allocation

JAVA supports dynamic dispatch through method rewriting. The Code is as follows:

Package com. bankht. Visitor;/*** @ Author: -AK47 * @ Creation Time: 10:41:46 ** @ Class description: supports dynamic dispatch for Java override through methods. Use the story of horse grazing as an example */public class horse {public void eat () {system. Out. println ("horse grazing ");}}

 

Package COM. bankht. visitor;/*** @ Author: -AK47 * @ Creation Time: 10:43:15 ** @ Class description: */public class Whitehorse extends horse {@ overridepublic void eat () {system. out. println ("white horse grazing ");}}

 

Package COM. bankht. visitor;/*** @ Author: -AK47 * @ Creation Time: 10:42:08 ** @ Class description: */public class Blackhorse extends horse {@ overridepublic void eat () {system. out. println ("dark horse grazing ");}}

 

Package COM. bankht. visitor;/*** @ Author: -AK47 * @ Creation Time: 10:42:34 ** @ Class description: */public class client {public static void main (string [] ARGs) {Horse H = new Blackhorse (); H. eat ();}}

Run:

Dark horse grazing

The static type of variable H is horse, while the actual type is Blackhorse. If the Eat () method in the last row above calls the Eat () method of the Blackhorse class, the printed above is "dark horse grazing". On the contrary, if the Eat () method above is () the method calls the Eat () method of the horse class, and the print is "horse grazing ".

Therefore, the core of the problem is that the Java compiler does not always know which code will be executed during compilation, because the compiler only knows the static type of the object and does not know the actual type of the object; the call of a method is based on the actual type of the object, rather than the static type. In this way, the Eat () method in the last row above calls the Eat () method of the Blackhorse class and prints the "dark horse grazing ".

Assigned type

The object to which a method belongs is called the method receiver. The method receiver and the method parameters are collectively referred to as the number of methods. For example, the test class in the following example

public class Test {    public void print(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 a parameter STR, which is of the string type.

You can divide object-oriented languages into single-assignment languages (uni-dispatch) and Multi-assignment languages (Multi-dispatch) based on how many types of data can be distributed ). A single assignment language selects a method based on the type of a single parcel. Multiple assignment languages select a method based on the type of more than one parcel.

C ++ and Java are both single-assignment languages. Examples of Multi-assignment languages include Clos and Cecil. According to this distinction, Java isDynamic Single-assignment LanguageBecause the dynamic distribution of this language only takes into account the type of the method receiver andStatic multi-assignment LanguageBecause the assignment of overload methods in this language takes into account the type of the method receiver and the types of all parameters of the method.

In a language that supports dynamic single assignment, there are two conditions that determine which operation a request will call: first, the request name, but the real type of the recipient. Single dispatch limits the method selection process so that only one parcel can be considered. This parcel is usually the method receiver. In Java, if an operation is performed on an object of unknown type, the actual type test of this object will only happen once, which is the feature of dynamic single assignment.

Double dispatch

One method decides to execute different code based on the two types of data sets, which is "Double dispatch ". The Java language does not support dynamic multi-distribution, which means that Java does not support dynamic dual-distribution. However, by using the design pattern, you can also implement dynamic dual-allocation in the Java language.

In Java, two methods can be called to achieve the goal of two distributions. The class diagram is as follows:

In the figure, there are two objects: West on the left and east on the right. Now, the West object first calls the goeast () method of the East object and passes it in. When the East object is called, the system immediately knows who the caller is based on the input parameters, and calls the gowest () method of the "Caller" object in turn. The control of the program is rotated to two objects through two calls. The time sequence is shown as follows:

In this way, two method calls occur, and the control of the program is transmitted to the east object by two objects like passing a pass. Then, the West object is returned to the east object.

However, if you pass back the ball, the problem of dual allocation cannot be solved. The key is how to use these two calls and the dynamic single dispatch function of the Java language, so that two single distributions can be triggered during the transfer process.

Dynamic Single Assignment occurs when the child class overrides the parent class method in Java. In other words, both West and East must be in their own type level structure, as shown in:

Source code

West class

public abstract class West {        public abstract void goWest1(SubEast1 east);        public abstract void goWest2(SubEast2 east);}

 

Subwest1 class

public class SubWest1 extends West{        @Override    public void goWest1(SubEast1 east) {                System.out.println("SubWest1 + " + east.myName1());    }        @Override    public void goWest2(SubEast2 east) {                System.out.println("SubWest1 + " + east.myName2());    }}

Subwest2 class

public class SubWest2 extends West{    @Override    public void goWest1(SubEast1 east) {                System.out.println("SubWest2 + " + east.myName1());    }        @Override    public void goWest2(SubEast2 east) {                System.out.println("SubWest2 + " + east.myName2());    }}

East class

public abstract class East {    public abstract void goEast(West west);}

 

Subeast1 class

public class SubEast1 extends East{    @Override    public void goEast(West west) {        west.goWest1(this);    }        public String myName1(){        return "SubEast1";    }}

 

Subeast2 class

public class SubEast2 extends East{    @Override    public void goEast(West west) {        west.goWest2(this);    }        public String myName2(){        return "SubEast2";    }}

 

Client type

Public class client {public static void main (string [] ARGs) {// combination 1 East = new subeast1 (); West = new subwest1 (); East. goeast (West); // combines 2 East = new subeast1 (); West = new subwest2 (); East. goeast (West );}}

The running result is as follows:

--------------------------------------------------------------------------------
Subwest1 + subeast1
Subwest2 + subeast1
--------------------------------------------------------------------------------


 

When the system is running, it first creates the subwest1 and subeast1 objects, then the client calls the goeast () method of subeast1, and passes in the subwest1 object. Because the subeast1 object overrides the goeast () method of its super class east, a dynamic single dispatch occurs at this time. When the subeast1 object is called, it will get the subwest1 object from the parameter, so it immediately calls the gowest1 () method of this object and passes it in. Because the subeast1 object has the right to select which object to call, a dynamic method assignment is performed at this time.

At this time, the subwest1 object obtains the subeast1 object. By calling the myname1 () method of this object, you can print your own name and the name of the subeast object. The sequence diagram is as follows:

Since the two names are from the East level structure and the other from the West level structure, their combination is dynamically determined. This is the implementation mechanism of dynamic dual-allocation.

Structure of visitor Mode

The visitor mode is suitable for systems with relatively undetermined data structures. It frees the coupling between the data structure and the operations acting on the structure, allowing the operation set to evolve relatively freely. The visitor mode is shown as follows:

Each node in the data structure can be called by a visitor. This node transmits a Node object to the visitor object, and the visitor object in turn performs operations on the Node object. This process is called "Double dispatch ". The node calls the visitor and passes it in. The visitor executes an algorithm on the node. The schematic diagram of the visitor mode is as follows:

The visitor mode involves the following roles:

Abstract visitor role:Declares one or more method operations to form interfaces that must be implemented by all specific visitor roles.

Specific visitor (concretevisitor) role:Implement the interface declared by the abstract visitor, that is, the Access Operations declared by the abstract visitor.

Abstract node role:Declare an acceptance operation and accept a visitor object as a parameter.

Specific node (concretenode) role:The acceptance operation specified by the abstract node is implemented.

Objectstructure role:You have the following responsibilities to traverse all elements in the structure. If necessary, a high-level interface is provided to allow the visitor object to access each element. If necessary, it can be designed as a composite object or aggregation, such as list or set.

Source code

As you can see, the abstract visitor role has prepared an access operation for each specific node. Because there are two nodes, there are two access operations.

Package COM. bankht. visitor. visitor;/*** @ Author: -AK47 * @ Creation Time: 10:50:06 ** @ Class description: You can see, the abstract visitor role prepares an access operation for each specific node. Because there are two nodes, there are two access operations. */Public interface visitor {/*** corresponds to the nodea access operation */Public void visit (nodea node ); /*** access operation corresponding to NodeB */Public void visit (NodeB node );}

 

Visitor visitora class

Package COM. bankht. visitor. visitor;/*** @ Author: -AK47 * @ Creation Time: 10:58:04 ** @ Class description: */public class visitora implements visitor {/*** corresponds to the nodea access operation */@ overridepublic void visit (nodea node) {system. out. println ("visitora:" + node. operationa ();}/*** corresponds to the access operation of NodeB */@ overridepublic void visit (NodeB node) {system. out. println ("visitora:" + node. operationb ());}}

 

Visitor visitorb type

Package COM. bankht. visitor. visitor;/*** @ Author: -AK47 * @ Creation Time: 10:58:21 ** @ Class description: */public class visitorb implements visitor {/*** corresponds to the nodea access operation */@ overridepublic void visit (nodea node) {system. out. println ("visitorb:" + node. operationa ();}/*** corresponds to the access operation of NodeB */@ overridepublic void visit (NodeB node) {system. out. println ("visitorb:" + node. operationb ());}}

 

Abstract node class

Package COM. bankht. visitor. visitor;/*** @ Author: -AK47 * @ Creation Time: 10:58:57 ** @ Class description: */public abstract class node {/*** accept operation */public abstract void accept (visitor );}

Specific node class nodea

Package COM. bankht. visitor. visitor;/*** @ Author: -AK47 * @ Creation Time: 10:59:45 ** @ Class description: */public class nodea extends node {/*** accept operation */@ overridepublic void accept (visitor) {visitor. visit (this);}/*** nodea-Specific Method */Public String operationa () {return "nodea ";}}

 

NodeB

Package COM. bankht. visitor. visitor;/*** @ Author: -AK47 * @ Creation Time: 10:59:59 ** @ Class description: */public class NodeB extends node {/*** Acceptance Method */@ overridepublic void accept (visitor) {visitor. visit (this);}/*** method specific to NodeB */Public String operationb () {return "NodeB ";}}

 

The role of the structure object holds an aggregation and provides the add () method to the outside world as a management operation for aggregation. By calling this method, you can dynamically Add a new node.

Package COM. bankht. visitor. visitor; import Java. util. arraylist; import Java. util. list;/*** @ Author: -AK47 * @ Creation Time: 11:00:15 ** @ Class description: */public class objectstructure {private list <node> nodes = new arraylist <node> ();/*** execute method operation */Public void action (visitor) {for (node: nodes) {node. accept (visitor) ;}}/*** Add a new element */Public void add (node) {nodes. add (node );}}

 

Client type

Package COM. bankht. visitor. visitor;/*** @ Author: -AK47 * @ Creation Time: 11:00:29 ** @ Class description: */public class client {public static void main (string [] ARGs) {// create a structure object objectstructure OS = new objectstructure (); // Add a node OS to the structure. add (New nodea (); // Add a node OS to the structure. add (New NodeB (); // create a visitor = new visitora (); OS. action (visitor );}}

 

Although there is not a complex object tree structure with multiple branches in this schematic implementation, the visitor mode is usually used to process complex object tree structures in the actual system, in addition, the visitor mode can be used to handle tree structures that span multiple hierarchical structures. This is what makes the visitor mode powerful.

Preparation Process sequence diagram

First, the schematic client creates a structure object and passes in a new nodea object and a new NodeB object.

Secondly, the client creates a visitora object and passes the object to the structure object.

Then, the client calls the structure object aggregation management method and adds nodea and NodeB nodes to the structure object.

Finally, the client calls the action method action () of the structure object to start the access process.

Access process sequence diagram

  

The structure object traverses all nodes in the cluster it saves. In this system, it is the nodes nodea and NodeB. First, nodea will be accessed. This access is composed of the following operations:

(1) The acceptance method accept () of the nodea object is called, and the visitora object itself is passed in;

(2) The nodea object calls the access method of the visitora object in turn and passes in the nodea object itself;

(3) The visitora object calls the special method operationa () of the nodea object ().

This completes the dual allocation process. Then, NodeB will be accessed. The access process is the same as that of nodea.

Advantages of visitor Mode

Good scalability

You can add new functions for elements in the object structure without modifying the elements in the object structure.

Good reusability

Visitors can be used to define the general functions of the entire object structure, thus improving the degree of reuse.

Separate irrelevant Behaviors

Independent behaviors can be separated by visitors, and relevant behaviors can be encapsulated together to form a visitor. In this way, each visitor has a single function.

Disadvantages of visitor Mode

It is difficult to change the object structure.

It is not suitable for situations where classes in the object structure change frequently. Because the object structure changes, the visitor's interface and visitor's implementation must change accordingly, and the cost is too high.

Destroy Encapsulation

The visitor mode usually requires the object structure to open internal data to the visitor and objectstructrue, which breaks the encapsulation of the object.

  

 

 

Related Article

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.