Decorator Mode
1. Intention
Dynamically add some additional responsibilities to an object. The decorator mode is more flexible than the subclass generation function. -- Wrapper.
Two motivations
Sometimes we want to add some functions to an object instead of the entire class.
For example, a graphical user interface toolbox allows you to add some features to any user interface component, such as borders or some actions, such as window scrolling.
Using the Inheritance Mechanism is an effective way to add functions. The border feature inherited from other classes can be used by instances of multiple subclasses.
However, this method is not flexible enough because the selection of borders is static and users cannot control the way and time to add borders to components.
One flexible way is to embed a component into another object and add a border to the object. We call this embedded object decoration.
This decoration is consistent with the component interface it decorated, so it is transparent to customers who use this component. It forwards customer requests to this component and
Some additional actions (such as drawing a border) may be performed before and after forwarding ).
Transparency allows you to recursively nest Multiple decorations and add any number of functions, as shown in.
Such a structure:
VisualcomponentIs an abstract class that describes a visual object. It defines interfaces for plotting and event processing.
Note:DecoratorClass to send the drawing request to its components, andDecoratorTo extend this operation.
The subclass of decorator allows you to add some operations for specific functions.
For example, if other objects know that there is a scrolldecorator object in the interface, these objects can be rolled through the scrollto operation of the scrolldecorator object.
This mode is very important because it makes decoration available anywhere in visualcomponent.
Therefore, customers generally do not feel the difference between decorated components and undecorated components, nor have any dependency with decoration.
DecoratorThere isComponentTo receive the component to be decorated.
Inheritance structure:
Or the combination method:
In this case, I think the following three methods are used:DeccoratorMaybe not,DecoratorMake objects decorated,
Pass the object to a decoration object that can be decorated. Not the object itself.
Although you can useDecoratorTransfer requests, but it is bound to make things more troublesome. Therefore, we still need to operate on the original object itself.
In this way, we need to maintain two objects ...... Trouble! Why ???
III applicability and Structure
Decorator Mode
1. If other objects are not affectedDynamic,TransparentTo add responsibilities to a single object.
2. Handle unrecoverable responsibilities.
3. When the subclass generation method cannot be used for expansion. One case is that there may be a large numberIndependent,
To support each combination, a large number of child classes are generated, which leads to explosive growth in the number of child classes. Another scenario is that the class definition is hidden, or the class definition cannot be used to generate a subclass.
Structure:
Component (visualcomponent)
Define an object interface to dynamically add responsibilities to these objects.
• Concretecomponent (textview)
Define an object and add some responsibilities to this object.
• Decorator
Maintain a pointer to the component object and define an interface consistent with the component interface.
• Concretedecorator (boaderdecorator, scrolldecorator)
Add responsibilities to the component.
• Decorator forwards the request to its component object and may execute some additional actions before and after the request is forwarded.
4. Effect Analysis
1. more flexible than static inheritance
You can use the add and remove methods to add and delete responsibilities at runtime.
The Inheritance Mechanism requires that a new subclass be created for each added responsibility. More flexible addition and Decoration:
Using the decorator mode, you can easily repeat a feature. For example, when adding a double border to a textview,
You only need to add two boarderdecorator. The two inheritance boarder classes are prone to errors.
2. avoid having too many features in the class at the level of the hierarchy.
The decorator mode provides an "pay-as-you-go" method to add responsibilities. You can build complex objects step by step through customization.
V.CodeImplementation
1 decorator
View code
# Include <iostream. h>
# Include <memory. h>
/* ---------------------------------------------------------------- */
/* Class visualcomponent */
/* ---------------------------------------------------------------- */
Class Visualcomponent
{
Public :
Visualcomponent (){}
Virtual Void Draw () = 0 ;
};
/* ---------------------------------------------------------------- */
/* Class textview */
/* ---------------------------------------------------------------- */
Class Textviewcontrol: Public Visualcomponent
{
# Define Content_len 100
Public :
Textviewcontrol ( Char * STR, Int Len)
{
Memset (m_content, 0 , Content_len );
Memcpy (m_content, STR, Len );
}
Virtual Void Draw ()
{
Cout < " Textviewcontrol draw content = " <M_content <Endl;
}
Private :
Char M_content [content_len];
};
/* ---------------------------------------------------------------- */
/* Class decorator */
/* ---------------------------------------------------------------- */
Class Decorator: Public Visualcomponent
{
Public :
Decorator (visualcomponent * component)
{
M_componnet = component;
}
Virtual Void Draw ()
{
M_componnet-> draw ();
Cout < " I am decorator draw " <Endl;
}
Private :
Visualcomponent * m_componnet;
};
/* ---------------------------------------------------------------- */
/* Class boarderdecorator */
/* ---------------------------------------------------------------- */
Class Boarderdecorator: Public Decorator
{
Public :
Boarderdecorator (visualcomponent * component, Int Boarderwidth): decorator (Component)
{
M_boarderwidth = boarderwidth;
}
Virtual Void Draw ()
{
Decorator: Draw ();
Cout < " I am boarderdecorator draw " <Endl;
This -> Drawborder ();
}
Protected :
Void Drawborder ()
{
Cout < " Drawborder m_boarderwidth = " <M_boarderwidth <Endl;
}
Private :
Int M_boarderwidth;
};
/* ---------------------------------------------------------------- */
/* Class scrolldecorator */
/* ---------------------------------------------------------------- */
Class Scrolldecorator: Public Decorator
{
Public :
Scrolldecorator (visualcomponent * component, Int Scrollheight): decorator (Component)
{
M_scrollheight = scrollheight;
}
Virtual Void Draw ()
{
Decorator: Draw ();
Cout < " I am scrolldecorator " <Endl;
This -> Drawscroll ();
}
Protected :
Void Drawscroll ()
{
Cout < " Drawscroll m_scrollheight = " <M_scrollheight <Endl;
}
Private :
Int M_scrollheight;
};
2 Test
View code
# include " decorator. h "
# include string . h>
int main ()
{< br> char STR [] = " textviewcontrol " ;
textviewcontrol * textview = New textviewcontrol (STR, strlen (STR);
scrolldecorator * scroll = New scrolldecorator (textview, 100 );
boarderdecorator * board = New boarderdecorator (scroll, 200 );
board-> draw ();
return 0 ;< BR >}
3 result
View code
Textviewcontrol draw con
I am decorator
I am scrolldecorator
M_scrollheight =100
I am decorator
I am boarderdecorator
M_boarderwidth =200
6. instance analysis
Decorator decoration or wrapper packaging of these words is too easy to think of is the graphical user interface, these controls are applied. However, this is just an image expression, not limited to this.
1 For example:
Streams is the basic abstract structure of most I/O devices. It provides operation interfaces for converting objects into byte or dense streams,
This allows us to convert an object into a file or a string in memory, which can be restored later. A Simple and Direct
The method is to define an abstract stream class, which has two subclasses: memorystream and filestream. But suppose we want to do the following:
• Use different compression methodsAlgorithm(Stroke encoding, Lempel-Ziv, etc.) to compress data streams.
• Simplify stream data to 7-Bit a s c I code characters so that it can be transmitted over a s c I channel.
The decorator mode provides a clever way to add these functions to stream. The class diagram below provides a solution to the problem.
The stream abstract class maintains an internal buffer and provides some operations (putint, putstring) to store data in the stream.
Once the buffer is full, stream calls the abstract operation handlebufferfull for actual data transmission.
This operation is redefined in filestream to transfer data in the buffer zone to a file.
The key class here is streamdecorator, which maintains a pointer to the component stream and forwards the request to it,
The streamdecorator subclass redefines the handlebufferfull operation and executes some additional actions before calling the handlebufferfull operation of streamdecorator.
For example, the compressingstream subclass is used to compress data, while ascii7stream converts the data into a 7-bit ASCII code.
Now we create the filestream class, which first compresses the data and then converts the compressed binary data into a 7-bit ASCII code,
We use compressingstream and ascii7stream to decorate filestream:
Stream * astream =NewAscii7stream (
NewCompressingstream (
NewFilestream ("Afilestream")
)
);
Astream-> putint (12);
Astream-> putstring ("Astring");
2Related mode:
- Adapter mode: the decorator mode is different from the adapter mode, because decoration only changes the responsibility of the object without changing its interface, and the adapter will give the object a new interface.
- Composite mode: decoration can be regarded as a degraded combination of only one component. However, decoration only adds some additional responsibilities to an object-it does not aim at object aggregation.
- Strategy Mode: With a decoration, you can change the appearance of an object, while the strategy mode allows you to change the kernel of an object. This is two ways to change objects.
After several examples, I have been slowly thinking that this mode is good!
There is an inexpressive feeling ...... He can separate several related things that you want to do to make things clearer...