Decorator mode
origin
Delphi's Decorator mode is extension on the basis of Decorator. For more information on Decorator mode, please refer to "Design Mode 115"
purpose
Dynamically add some responsibilities to an object. In terms of increased function, Decorator is more flexible than adding subclasses.
motivation
We often add some new responsibilities for some individual objects, not all classes. Suppose we have a set of classes to output text lines. Abstract TTextStream defines some interfaces, procedural, such as TTextFile, TLinePrinter, TclipboardStream implemented these interfaces.
Now, suppose we want to add some new responsibilities to these classes such as text buffers, size constant conversion, text analysis.
The inheritance mechanism is an effective way to add functions. The buffer can be used by the instance of multiple subclasses from the TTextStream class. But not very flexible. Because the choice of the buffer is static. The client cannot control the way and timing of the selection buffer. Thus, the burden of the field of abstract class TtextStream is added to control the buffer and will be brought into its first instance. It is usually a lightweight of a high level (abstract) base class. Increased irregularization and original analysis in the base class make it the most and very cumbersome!
If you don't want to create a base class, you will generate a problem. There is a case where a large number of independent inherits may be, but the waterfall forms produces a large number of subclasses to support different combinations such as: TBuftextFile, TscRambledTextFile, TBufscRambleTextFile, TBuflineprinter, TscRambledLineprinter, and others. The same problem occurs, if the class definition is hidden or invisible to subclass. For example, if you want to join a new responsibility in the high-level class of the third component library, try to join Delphi's TSTream to join a new responsibility!
A flexible approach is to embed the text stream into another object, add this object to the buffer or irregularization. We call this embedded object for decoration (Decorator). This decoration is consistent with the text stream component interface, because it is transparent to the use of text stream client. The holding interface in Delphi is consistent means that from a commonly inherited inheritance, TTextStream. Decoration will go forward to the text stream, and may be forwarded to some additional actions (such as buffers, irregular), transparency make you can recursively, multiple decorations, can add any more Function.
Assume that the interface of the TTEXTSTREAM is as follows:
Type
TtextStream = Class (TOBJECT)
protected
Function GetendoftExt: Boolean; Virtual; Abstract;
public
Function Readline: String; Virtual; ABSTRACT;
Procedure WriteLine (Const line: string); Virtual; Abstract;
Property endoftext: Boolean Read GeTendoft;
END;
Use Adapter to create some real text stream components such as TLineprinter, TtextFile, more other. In order to keep the interface consistent. Using Decorator mode, we can flexibly add new features for all text streams. Suppose we name the decorative class TTEXTFILTER. This class is inherited from TtextStream to protect the TtextStream certificate, which also contains references to TtextStream instances TextStream. Class TTEXTFILTER does not implement any new features, it is simply forward to the Class TEXTSTREAM for a request (method call) of all client programs. Subsequent, TUPPERCASEFilter joined some new duties through simple overloaded decoration. The following flowchart shows how tuPpercaseFilter is called a client program called TTEXTSTREAM.
This mode is most important that the decorative class displays any part of TtextStream to display. In this way, customers do not differ from the classes that call the decorative class and the end of the decoration, and they do not have any dependencies for decorative classes. In the example of this unit, the client does not know that its text is converted to uppercase before the actual write operation.
application
The following code demonstrates the application of the decorative mode of the class. The TTextStream in the example defines an abstract interface for the decorative TTextFilter.
Type
TtextStream = Class (TOBJECT)
protected
Function GetendoftExt: Boolean; Virtual; Abstract;
public
Function Readline: String; Virtual; ABSTRACT;
Procedure WriteLine (Const line: string); Virtual; Abstract;
Property endoftext: Boolean Read GeTendoft;
END;
TtextFilter = Class (TtextStream)
Private
FOWNSSTREAM: BOOLEAN;
FTextStream: TtextStream;
protected
Function GetendoftExt: boolean; Override;
Function GetTextStream: TTEXTSTREAM;
Procedure setTextStream (Value: TtextStream);
public
Constructor Create (AtextStream; Aownsstream: Boolean);
DESTRUCTOR DESTROY; OVERRIDE;
Function Readline: String; Override;
Procedure WriteLine (const line: string); OVERRIDE;
Property OwnsStream: Boolean Read Fownsstream Write Fownsstream;
Property TextStream: TtextStream ReadTextStream Write setTextStream;
END;
Code description:
• The properties TextStream contains references to decorated text stream objects. TextStream has a read and write operation. This is more flexible for future generations. A similar pattern of Proxy mode, by reading, writing methods in Proxy mode is also a good application. Please refer to "Design Mode" for Proxy mode.
· Attribute ownsStream used to TEXTSTREAM ownership. In the implementation code below, you can see whether the TTEXTFILTER class is judged when all of its text stream is true. It takes the role of helping decorative clearance.
· TextStream, Ownsstream is two parameters of the decorative structure. · Implementing the decorative class overloads more than READLINE, WRITELINE, GeEndoftExt. And the implementation is added.
Here is its implementation part of the code:
Constructor TTextFilter.create (AtextStream; Aownsstream: Boolean);
Begin
Inherited Create;
TextStream: = ATEXTSTREAM;
Ownsstream: = aownsstream;
END;
Destructor TTextFilter.Destroy;
Begin
TextStream: = NIL;
Inherited destroy;
END;
Function TTextFilter.GetendOfText: Boolean;
Begin
Result: = textStream.GETENDEXT;
END;
Function TTextFilter.getTextStream: TtextStream;
Begin
Result: = fTextStream;
END;
Function TTextFilter.Readline: string;
Begin
Result: = TextStream.readLine;
END;
Procedure TtextFilter.SetTextStream (Value: TtextStream);
Begin
IF value <> fTextStream Then
Begin
IF OwnstextStream Then fTextStream.free;
FTextStream: = Value;
END;
END;
Procedure TTextFilter.writeline (const line: string);
Begin
TextStream.writeline (LINE);
END;
One is very interested in these implementation code:
· Decorative behavior method: Readline, WriteLine, getndoftext is just a simple call corresponding TextStream method.
• The setTextStream method is allocated before the new value is safely released.
· The release function will textStream: = NIL because the current text stream is possible in SetTextStream.
It is now possible to create a filter that converts text into uppercase.
Interface part of the code:
Type
TuppercaseFilter = Class (TTEXTFILTER)
public
»Function Readline: String; Override;
»Procedure WriteLine (const line: string); OVERRIDE;
END;
IMPLEMENTATION
Function Tuppercasefilter.Readline: string;
Begin
»Result: = Uppercase (Inherited Readline);
END;
Procedure tuppercasefilter.writeline (const line: string);
Begin
»Inherited WriteLine (Uppercase (Line);
END;
This decorative class can be used by any TTEXTSTREAM target:
Function Tclient.createoutput: TTEXTSTREAM;
Begin
»{Create a base class}
»Case Destination of
»DSFILE: Result: = TtextFile.create (getFileName, Fmcreate);» dsprinter: result: = tlineprinter.create;
»END;
»{Judgment whether it is decorated, and use the same parameters
»Important is that we don't have to care about decorating TTEXTFILE, or tLineprinter}
»If ConvertTOUPPERCASE THEN
»Result: = tuppercasefilter.create (result, true);
END;
Procedure Tclient.listContents;
VAR
T: TTEXTSTREAM;
Begin
T: = CreateOutput;
{Here, we don't know if we use decoration}
Try
{Tour to write}
T.WriteLine ('contents');
Finally
T.free;
END;
END;
Delphi instance
Is being organized. . .