For example, we have the following classes:
Class cgshape
{
Public:
~ Cgshape ();
Virtual void draw () = 0;
};
Class cgrectangle: Public cgshape
{
Public:
Void draw ();
};
Class cgsquare: Public cgshape
{
Public:
Void draw ();
};
Class cgcircle: Public cgshape
{
Public:
Void draw ();
};
If some code users have a special need to draw the central point of the image while drawing the image, what should we do?
Obviously, you cannot directly add the code for drawing the center point to the draw method of each class, because not all users need this function.
Then we can add a bool member variable m_bdrawcenter to the base class cgshape, and add a public method setdrawcenter to set the variable value, then, in the draw method of each subclass, determine whether to draw the center point based on the value of the variable m_bdrawcenter. Before calling the draw method, you must call the setdrawcenter method to set m_bdrawcenter to true.
Another method is to inherit the class cgrectangle, cgsquare, and cgcircle respectively. In each subclass, reload the draw method and add the code to draw the center point.
The above two methods are both feasible, but let's take a closer look at the defects of the two methods:
Method 1: add the code for judging the value of m_bdrawcenter and the Code for drawing the center point in the draw method of each class. These codes are repeated in each class, the addition is also boring. If there are many classes, the programmers who do the job will crash. The most important thing is that if the above classes are included in the library files and there is no source code, this method will not work at all.
Method 2 seems to be in line with object-oriented design (OOD) and does not need the source code of the above classes. However, this will generate a large number of child classes and add the class hierarchy. In addition, each inherited subclass also modifies the draw method, and the Code for adding the painting center is repeated.
To avoid all the defects mentioned above, we can use the decorator mode. Take a look at the following class:
Class cgdrawshapewithcenter: Public cgshape
{
Public:
Cgdrawshapewithcenter (cgshape * pshape );
Void draw ();
PRIVATE:
Cgshape * m_pshape;
};
Cgdrawshapewithcenter: cgdrawshapewithcenter (cgshape * pshape)
{
// Obtain the pointer to a specific image
M_pshape = pshape;
}
Void cgdrawshapewithcenter: Draw ()
{
M_pshape-> draw ();
// Add the code for drawing the center point here
}
This class is very simple to use. The following function is used to draw a circle and a circle center:
Void drawcirclewithcenter ()
{
Cgcircle circle;
Cgdrawshapewithcenter shape (& circle );
Shape. Draw ();
}
In the class cgdrawshapewithcenter, we use a pointer to cgshape to obtain control of the image to be drawn. The user does not feel any difference when calling the draw method. We will not modify any classes, nor produce a large number of sub-classes, nor meet the needs of special users when there is no repeated code.
Of course, the example above is very simple, but it is sufficient to explain the advantages of the decorator mode. Note that the class cgdrawshapewithcenter must implement all cgshape-like interfaces. In the interface implementation that does not need to be modified, you only need to call the corresponding method of m_pshape pointing to cgshape.
Now, someone may ask: why does the class cgdrawshapewithcenter inherit from the class cgshape? From the code above, writing a class cgdrawshapewithcenter can also implement all the functions. However, please refer to the following function:
Void drawshape (cgshape * pshape)
{
Pshape-> draw ();
}
This function is written by the user to draw images. If the class cgdrawshapewithcenter is not inherited from the class cgshape, you must modify this function to draw the center of the image while drawing the image:
Void drawshape (cgdrawshapewithcenter * pshape)
{
Pshape-> draw ();
}
If the class cgdrawshapewithcenter is inherited from the class cgshape, you do not need to modify the above function. The class polymorphism is used to pass the pointer of A Class cgdrawshapewithcenter object to the function. For example:
Cgcircle circle;
Cgdrawshapewithcenter shape (& circle );
Drawshape (& shape );
That is to say, cgdrawshapewithcenter can be used for all cgshape locations, so as to exert the powerful function of C ++ class polymorphism. In this case, the amount of user code modifications can be minimized. The biggest advantage of doing so is that the decorator class cgdrawshapewithcenter can be modified by other decorator classes. In fact, the most subtle part of the decorator mode is that the decorator class inherits from the base class of the class to be modified and has a member pointing to the pointer of the class to be modified.