The DECORATOR mode, also known as Wrapper, is an Object Schema that dynamically adds some additional responsibilities to an object. The Decorator mode is more flexible than the subclass generation function. It replaces the inheritance relationship between classes by using the association relationship between objects. The introduced decoration class can call the method of the decoration class and add new business logic, to expand the decoration class. Both the decoration mode and the adapter mode are called wrapper, but they are different. The decoration mode only adds new responsibilities on the basis of the original object without changing the interface provided externally. The adapter mode is used to solve the incompatibility problem between interfaces, which will inevitably change the interfaces provided externally.
I. Application scenarios
1. Add roles to a single object dynamically and transparently without affecting other objects. The decoration mode uses Object combination instead of class inheritance to expand the function. Therefore, you can dynamically add, switch, and delete the objects to be expanded without affecting other objects.
2. Deal with the irrevocable responsibilities. For objects that require a specific responsibility, you only need to associate the corresponding decoration objects.
3. When the system cannot be extended or inherited, It is not conducive to system expansion and maintenance. One case is that a large number of independent extensions exist in the system. To support the combination of each extension or extension, a large number of subclasses are generated, which leads to explosive growth in the number of subclasses. Another possible reason is that the class definition is hidden or the class cannot be inherited. For example, the class in java is defined as final class.
Ii. UML diagram
Iii. Java implementation
Package study. patterns. decorator;/*** decoration mode: reduces the Coupling Degree of the system and dynamically adds or deletes the responsibilities of objects. * The specific component classes to be decorated and the specific decoration classes can be changed independently, * To add new component classes and decoration classes. * If you need to add a new component class or a new decoration class to the original system, * you do not need to modify the existing class library code, you only need to use them as the subclass of the abstract component class or the abstract decoration class. * @ author qbg */public class DecoratorPattern {public static void main (String [] args) {String test = "test123 "; // use the default decoration class and do not use the decoration class. The effect is the same as IStream dStream = new StreamDecorator (new MemoryStream (); dStream. write (test); String r0 = dStream. read (); System. out. println ("======= use the default decoration class:" + r0); // use the compressed decoration class IStream cStream = new CompressingStream (new MemoryStream (); cStream. write (test); String r1 = cStream. read (); System. out. println ("====== use compressed decoration class:" + r1); // use ASCII decoration class IStream aStream = new ASCII7Strem (new FileStream (); aStream. write (test); String r2 = aStream. read (); System. out. println ("======= use ASCII decoration class:" + r2); // use the ASCII decoration class for encoding conversion first, then, use the compression decoration class to compream caStream = new ASCII7Strem (new CompressingStream (new FileStream (); caStream. write (test); String r3 = caStream. read (); System. out. println ("====== use ASCII and compressed decoration class:" + r3 );}} /*** I/O Stream interface */interface IStream {/*** read stream */public String read (); /*** write stream */public void write (String str);}/*** the stream medium is memory type */class MemoryStream implements IStream {private String stream; @ Overridepublic String read () {System. out. println ("read stream from memory... "); return stream ;}@ Overridepublic void write (String stream) {System. out. println ("Write stream to memory... "); this. stream = stream ;}/ *** the stream media is the file System */class FileStream implements IStream {private String stream; @ Overridepublic String read () {System. out. println ("read stream from file... "); return stream ;}@ Overridepublic void write (String stream) {System. out. println ("Write stream to file... "); this. stream = stream ;}/ *** default stream decoration implementation class */class StreamDecorator implements IStream {private IStream stream; public StreamDecorator (IStream stream) {this. stream = stream;} @ Overridepublic String read () {return this. stream. read () ;}@ Overridepublic void write (String stream) {this. stream. write (stream) ;}/ *** converts stream data to a 7-bit ASCII code */class ASCII7Strem extends StreamDecorator {public ASCII7Strem (IStream stream) {super (stream );} @ Overridepublic void write (String stream) {super. write (toAscii7 (stream);}/** additional responsibilities */private String toAscii7 (String stream) {System. out. println ("convert data to 7-bit ASCII Code"); return "ASCII [" + stream + "]" ;}} /*** compressing stream Data */class CompressingStream extends StreamDecorator {public CompressingStream (IStream stream) {super (stream) ;}@ Overridepublic void write (String stream) {super. write (compress (stream);}/** additional responsibilities */private String compress (String stream) {System. out. println ("compressed data"); return "compressed [" + stream + "]" ;}}
Running result:
Write stream to memory... read stream from memory... ======= use the default decoration class: test123 compressed data into the memory to write the stream... read stream from memory... ======= use a compressed decorative class: compress [test123] to convert the data into a 7-bit ASCII code and write the stream into the file... read stream from file... ====== use ASCII decoration class: ASCII [test123] to convert the data into a 7-bit ASCII code and compress the data into a stream into the file... read stream from file... ======= use ASCII and compressed decorative classes: compression [ASCII [test123]
Iv. Advantages and Disadvantages
Advantages:
1. For the function of extending an object, the decoration mode is more flexible than inheritance, and does not cause a sharp increase in the number of classes.
2. You can expand the functions of an object in a dynamic way. You can select different decoration classes at runtime through the configuration file to achieve different behaviors.
3. You can decorate an object multiple times. By using different decorative classes and the arrangement and combination of these decorative classes, you can create a combination of many different behaviors to obtain more powerful objects.
4. The specific component classes and specific decoration classes can be changed independently. You can add new specific component classes and specific decoration classes as needed. The original class library code does not need to be changed and complies with the "open and closed principle ".
5. avoid having too many features in the class at the upper level of the hierarchy. The simpler the High-level class, the better its scalability and flexibility. You can define a simple class and then use the Decorator class to gradually add features to it.
Disadvantages:
1. Many small objects are generated during system design using the decoration mode. The difference between these objects is that they are connected in different ways, rather than their classes or attribute values, the generation of a large number of small objects is bound to occupy more system resources, affecting program performance in a certain program, and increasing the complexity of the learning system.
2. The decoration mode provides a more flexible and mobile solution than inheritance, but it also means that it is more error-prone and difficult to troubleshoot than inheritance. For objects decorated multiple times, you may need to troubleshoot errors during debugging.
3. the Decorator is different from its Component. The Decorator is only transparent, so the client should not rely on Decorator for use.