Visitor ModeIt is a method to separate the data structure and behavior of objects. Through this separation, you can add new operations (that is, visitors) to an existing class or group (that is, visitors) they do not need to be modified. The visitor mode is a behavior mode.
Why use the visitor mode?
How to extend an existing class hierarchy to implement new behaviors? The general method is to add a new method to the class. But what if the new behavior is incompatible with the existing object model? Also, the class hierarchy designer may not be able to predict which features will be needed in the future development process. And, if the existing class hierarchy cannot be modifiedCodeHow can we expand behavior?
The answer is to use the visitor mode in the class hierarchy design.
Roles involved in the visitor mode:
1) Visitor (visitor)
The visitor's abstract interface accesses the element (Data Structure) through the visit (element) method to perform operations on the element.
2) specific visitor (concretevisitor)
The visitor's implementation class.
3) element, that is, the visitor
Use the accept (visitor) method to receive access from the visitor.
4) specific elements (concreteelement)
The specific implementation class of the element.
5) objectstructure)
A composite object with a group of elements. Objectstructure itself can also be used as a visitor.
Structure of visitor mode (downloaded online ):
When an application meets the following conditions, we can use the Visitor Design Mode:
1) An object structure contains many class objects with different interfaces. You want to perform operations on these objects dependent on their specific classes.
2) You need to perform many different and unrelated operations on the objects in an object structure, and you want to avoid causing these operations to "pollute" the classes of these objects. Visitor allows you to define related operations in a class.
3) when the object structure is shared by many applications, use the visitor mode to allow each application to only include the operations needed.
4) classes that define the object structure are rarely changed, but new operations are often needed in this structure. Changing the object structure class requires redefining the interfaces for all visitors, which may be costly. If the object structure class changes frequently, it may be better to define these operations in these classes.
Advantages:
1) it is easy to add methods that are not yet taken into account. (This is also why visitors are used: Extended features)
2) classes can be made smaller, because the methods that are rarely used can be defined externally. (This means that if a method is often used, it is best to define it in the class; of course, this method is not taken into account in the first definition)
Disadvantages:
1) The visitor role is not suitable for situations where the specific element roles change frequently. (For example, if a new element class is added, the visitor interface needs to be changed .)
2) to perform operations related to the element role, the element role must expose its internal attributes, which destroys the encapsulation of the element role. The coupling between the visitor and the accessed object is great.
3) The information that can be transmitted between elements and visitors is limited, which often limits the use of the visitor mode. (Because visitors cannot directly access the private data of elements)
Example:
# Include <iostream> <br/> # include <list> <br/> # include <string> </P> <p> using namespace STD; </P> <p> class cperson; <br/> class cstudent; <br/> class cteacher; </P> <p> class cvisitor; <br/> class cprinter; </P> <p> // element (visitor) <br/> class cperson // pure virtual class <br/>{< br/> protected: <br/> string name; // or change it to an array <br/> int gender; </P> <p> cperson () <br/>{< br/>}</P> <p> Public: <br/> virtual void accept (cvisitor &) // = 0; // pure virtual letter Count <br/>{< br/>}< br/> Public: <br/> void setname (const string & name) <br/>{< br/> name = Name; <br/>}</P> <p> string getname () const <br/>{< br/> return name; <br/>}</P> <p> void setgender (const Int & Gender) <br/>{< br/> gender = gender; <br/>}</P> <p> int getgender () const <br/>{< br/> return gender; <br/>}</P> <p> }; </P> <p> // visitor <br/> class cvisitor <br/> {<br/> Public: <br/> virtual void visit (cstudent &) = 0; <Br/> virtual void visit (cteacher &) = 0; <br/>}; </P> <p> // specific element <br/> class cstudent: public cperson <br/>{< br/> PRIVATE: <br/> int grade; // Grade <br/> Public: <br/> cstudent (string name, int gender, int grade) <br/>{< br/> name = Name; <br/> gender = gender; <br/> grade = Grade; <br/>}< br/> Public: <br/> virtual void accept (cvisitor & printer) // virtual function <br/>{< br/> printer. visit (* This); <br/>}</P> <p> void setgrade (INT g Rade) <br/>{< br/> grade = Grade; <br/>}</P> <p> int getgrade () const <br/>{< br/> return grade; <br/>}< br/> }; </P> <p> // specific element <br/> class cteacher: Public cperson <br/>{< br/> PRIVATE: <br/> int service_time; // length of service <br/> Public: <br/> cteacher (string name, int grade, int servicetime) <br/>{< br/> name = Name; <br/> gender = Grade; <br/> service_time = servicetime; <br/>}</P> <p> public: </P> <p> virtual void accept (CV Isitor & printer) <br/>{< br/> printer. visit (* This); <br/>}</P> <p> void setservicetime (INT servicetime) <br/>{< br/> service_time = servicetime; <br/>}</P> <p> int getservicetime () const <br/>{< br/> return service_time; <br/>}< br/> }; </P> <p> // visitor <br/> // here, this class prints the information of specific elements (that is, displayed on the screen ), you can print different content as needed. <Br/> // a visitor is a policy. You can create a new visitor based on your needs without modifying the specific elements (that is, the visitor ). <Br/> class cprinter: Public cvisitor <br/>{< br/> Public: <br/> void visit (cstudent & S) <br/> {<br/> cout <"Student:" <Endl; <br/> cout <"/T name:" <S. getname () <Endl; <br/> If (S. getgender () = 0) <br/> cout <"/T Gender:" <"female" <Endl; <br/> else <br/> cout <"/T Gender:" <"male" <Endl; <br/> cout <"/T grade: "<S. getgrade () <Endl; <br/>}</P> <p> void visit (cteacher & T) <br/>{< br/> cout <"teach Er: "<Endl; <br/> cout <"/T name: "<t. getname () <Endl; <br/> If (T. getgender () = 0) <br/> cout <"/T Gender:" <"female" <Endl; <br/> else <br/> cout <"/T Gender:" <"male" <Endl; <br/> cout <"/T service time: "<t. getservicetime () <Endl; <br/>}< br/>}; </P> <p> // object structure <br/> // here, organization is an organization (for example, a group composed of tree planting festival to plant trees). There are several teachers and several students. <Br/> class organization <br/> {<br/> PRIVATE: <br/> typedef list <cperson *> cmemberlist; <br/> cmemberlist member_list; </P> <p> Public: </P> <p> void add (cperson * person) // Add a person. This is just an example, without considering repeated personnel. <Br/> {<br/> // note: the Space indicated by person must be the space requested by the new operator. </P> <p> member_list.push_back (person ); <br/>}</P> <p> // This is just an example. Therefore, operations such as member deletion are omitted. </P> <p> void printmembers (cprinter & printer) // output member list <br/>{< br/> cmemberlist: iterator itr = member_list.begin (); <br/> for (; itr! = Member_list.end (); ++ itr) <br/>{< br/> (* itr)-> Accept (printer ); <br/>}</P> <p> ~ Organization () <br/>{< br/> // Delete the requested space; C ++ is troublesome <br/> cmemberlist: iterator itr = member_list.begin (); <br/> for (; itr! = Member_list.end (); ++ itr) <br/>{< br/> Delete * itr; <br/>}< br/> }; </P> <p> int main () <br/> {<br/> organization planting; // tree planting Organization <br/> planting. add (New cteacher ("Johnny", 1, 10); <br/> planting. add (New cstudent ("Catherine", 0, 1); <br/> planting. add (New cstudent ("Peter", 1, 2); </P> <p> cprinter printer; // visitors can also be viewed as a strategy <br/> planting. printmembers (printer); </P> <p> return 0; <br/>}
After that:
After the visitor mode is used, you only need to implement a specific visitor role to add new operations to the original class hierarchy without modifying the entire class hierarchy. In addition, this meets the requirements of the "open and closed principle. In addition, each specific visitor role corresponds to a related operation. Therefore, if the demand for an operation changes, you only need to modify a specific visitor role without changing the entire class level. However, the principle of "open and closed" is always one-sided. If the class hierarchy in the system changes, what will happen to the visitor mode? You must modify the visitor role and each specific visitor role.
The Pattern Design Teaching Material book often mentions one sentence: discovering and encapsulating changes. Whether the visitor mode is used depends on (or foreseeable) What is "change. In the visitor mode, "change" is mainly the visitor, followed by the object structure. However, if the (specific) elements also change, the visitor mode will never be used, because the maintenance will be too poor if you "pull the whole body.
I am wondering why the visitor mode is used:
The object structure uses the (specific) element (that is, the visitor), while the (specific) element has incomplete functions, but it is not good to directly add the function to the element (such: it is not allowed to modify the element, or adding less commonly used functions will make the class too bloated, etc.), then we will define a helper class (that is, the visitor) to complete this function. As a result, we add an accept (visitor) method to the element (that is, the visitor) as an interface for foresight. Add new functions to the element, and add new visitor classes.
References:
1. Beginner's Guide to design patterns, translated by Xu yingxiao, Mechanical Industry Press
2. Copy it online from the east to the west.