Prototype mode in Design Mode

Source: Internet
Author: User

First, we will introduce an example in terms 29 of the virtual constructor and prototype modes in "C ++ common knowledge essential intermediate programming" (the Chinese translation is called "C ++:

Suppose you are in a Swedish restaurant and want to order food. Unfortunately, your Swedish level is limited to the technical field or "Foul Mouth" (generally the combination of the two ). The menu is written in Swedish. You cannot understand it, But you notice that a gentleman opposite the restaurant is enjoying the meal. So you called the waiter and said:

If the gentleman is eating fish, I just need a fish. If he is eating pasta, I will have pasta. If he is eating eel, I will have it. If he is in the fruit of kumquat, I will order it.

Is this reasonable? Of course not (unless otherwise mentioned, you may not want to order pasta in a Swedish Restaurant ). This"ProgramThere are two basic problems. First, this method is tedious and inefficient. Second, such inquiries may end with failures. If you have asked this series of questions, but you still haven't guessed what the gentleman is eating, what will happen? The waiter will leave, leaving you hungry and alone. To put it back, even if you happen to know all the content of the menu, you can make sure that the order is successful. But if you go to that restaurant next time, the menu has been changed, your problem list becomes invalid or incomplete.

Obviously, the proper way is to call all the waiters and say, "I want something the gentleman is eating ."

If the waiter sticks to the literal meaning and understands what you mean, he will take half of the gentleman's food and take it to your desk. However, such behavior hurts feelings and may even lead to a food competition. When two diners try to consume the same food at the same time, this unpleasant thing may happen. If the waiter is familiar with his business, he will give you a copy of the gentleman's food and will not affect the state of the copied food.

There are two main reasons for using "clone": You must (or prefer) Keep "unaware" of the exact type of the object being processed; you do not want to change the cloned original object, and do not want to be affected by the original object.

In C ++, a member function that provides the ability to clone objects is traditionally called a "virtual constructor ". Of course, there is no virtual constructor, but a copy of the generated Object usually involves indirect calls to the constructor of its class through a virtual function. Therefore, even if it is not a real virtual constructor, the effect is also a virtual constructor. Recently, this technology has been used as an instance of prototype mode.

Of course, we must understand the object to which it points. In this example, you only need to know what is needed is a meal.

 
ClassMeal {Public:Virtual~Meal ();Virtual VoidEat () =0;VirtualMeal * clone ()Const=0;//...};

the meal type provides the cloning capability through the clone member function. The clone function is actually a specialized factory method mode, which creates an appropriate product, you can also call Code without knowing the exact types of context and product classes. The specific classes derived from meal (that is, those actually existing meal listed on the menu) must provide an implementation for the pure virtual clone operation:

  class  spaghetti:  Public   meal {  Public  : Spaghetti (  const  spaghetti &); ///   copy constructor   void   eat (); spaghetti  * clone ()  const  {  return   New  spaghetti (*  This ); ///   call the copy constructor  } ///  ... }; 

With this simple framework, you can generate any type of meal replicas without having to know the details of the actual type of meal being copied. Note: The following Code does not mention a specific derived class, so the code will not be coupled with any current (or future) meal derived class.

 
ConstMeal * m = thatguysmeal ();//No matter what he is eating ......Meal * mymeal = m-> clone ();//I want the same copy as him!

In fact, it is entirely possible that we finally have some food we have never heard. Actually. Using prototype mode, you do not know the existence of a type and will not create any obstacles for this type of object. The above multi-state code may be compiled and released. If a new meal type is added to add functions in the future, you do not need to re-compile the code.

This example illustrates some of the advantages that are "unknown" in software design, especially in the Framework Structure Software Design for customization and expansion. Remember: The less you know, the better!

It can be seen from the above that prototype actually gets a copy, and the copied content is generally uninformed. Copy, C ++ has a good member function, that is, the copy constructor, for selection. When talking about the replication constructor, we generally talk about deep copy and shallow copy. In the prototype example, I will give an example of deep copy.

The typical structure of the prototype mode is:

First, we will describe the relationship between classes in Object-Oriented UML. The relationships between classes and objects and classes can be classified in the following two directions:

Vertical relationship: inheritance and implementation

Horizontal relationship: dependency, association, aggregation, and combination

UML is as follows:

Vertical relationship:

Inheritance implementation

Generalize (generalized) Realize (Implementation)

Horizontal relationship:

Dependency (dependency) Association (association)

Aggregation (aggregation) composition (combination)

For the meanings of specific links, see related UML books.

The specific prototype example (the Deep copy problem is added) is as follows:

 //  Prototype. h  # Ifndef prototype_h  # Define Prototype_h Class  Prototype {  Public  :  Virtual ~ Prototype (); Virtual Prototype * clone () Const = 0  ;  Protected  : Prototype ();};  Class Concreteprototype: Public  Prototype {  Public  : Concreteprototype (  Int X = 0 , Char * Name =0  ); Concreteprototype (  Const Concreteprototype & RHS); concreteprototype & Operator = ( Const Concreteprototype & RHS ); ~ Concreteprototype ();  Public  : Prototype * Clone () Const  ;  // Concreteprototype * clone () const;      Void Set_x ( Const   Int  X );  Int Get_x () Const  ;  Void Set_name ( Const   Char * Name );  Char * Get_name () Const  ; Private  :  Int  _ X;  Char * _ Name ;};  # Endif 
 //  Prototype. cpp # Include "  Prototype. h  "  # Include < String . H> //  Prototype Prototype: Prototype () {} prototype :: ~ Prototype (){}  //  Concreteprototype Concreteprototype: concreteprototype ( Int X, Char * Name) {_ x = X;  If (Name! = 0  ) {_ Name = New   Char [Strlen (name) +1  ];  //  Strcpy (_ name, name );  Strncpy (_ name, name, strlen (name); _ name [strlen (name)] = '  \ 0  '  ;} Concreteprototype: concreteprototype (  Const Concreteprototype & RHS) {_ x = RHS. _ x; _ name = New   Char [Strlen (RHS. _ name) + 1  ];  //  Strcpy (_ name, RHS. _ name );  Strncpy (_ name, RHS. _ name, strlen (RHS. _ name); _ name [strlen (RHS. _ name)] = '  \ 0  '  ;} Concreteprototype & Concreteprototype :: Operator = ( Const Concreteprototype & RHS ){  If (This ! = & RHS) {_ x = RHS. _ x; Delete [] _ name; _ name = New   Char [Strlen (RHS. _ name) + 1  ];  //  Strcpy (_ name, RHS. _ name );  Strncpy (_ name, RHS. _ name, strlen (RHS. _ name); _ name [strlen (RHS. _ name)] = '  \ 0  ' ;}  Return * This  ;} Concreteprototype :: ~ Concreteprototype (){  If (_ Name! = Null) {Delete [] _ name ;}}  Int Concreteprototype: get_x () Const  {  Return  _ X ;}  Void Concreteprototype: set_x ( Const  Int  X) {_ x = X ;}  Void Concreteprototype: set_name ( Const   Char * Name ){  If (Name! = Null) {_ name = New   Char [Strlen (name) + 1  ]; Strncpy (_ name, name, strlen (name); _ name [strlen (name) +1 ] = '  \ 0  '  ;}}  Char * Concreteprototype: get_name () Const  {  Return  _ Name;} prototype * Concreteprototype: Clone () Const  {  Return   New Concreteprototype (* This );} 
 //  Main. cpp # Include <iostream> # Include  "  Prototype. h  "  Using   Namespace  STD;  Int  Main () {prototype * PP = New Concreteprototype ( 100 , " Chenyuming  "  ); Prototype * PP2 = PP-> Clone (); cout <Static_cast <concreteprototype *> (pp2)-> get_x () < "  \ T  " <Static_cast <concreteprototype *> (pp2)-> get_name () < Endl;  Return   0  ;} 

Running result:

 
100Chenyuming

Finally, I want to mention: In prototype. in H, concreteprototype * clone () const is commented out. This line of code is because I use vc6.0 to test the above Code, concreteprototype * clone () const is acceptable according to Clause 31 of the C ++ mandatory meeting for the covariant return type. I guess it is the reason for the compiler, please try and tell me.

 

 

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.