Decorative mode is also known as packaging (Wrapper) mode. Adornment mode extends the functionality of the object transparently to the client, and is an alternative to the inheritance relationship.
structure of the decoration mode
Decorating mode dynamically attaches more responsibility to an object in a transparent manner to the customer. In other words, the client does not feel that the object is different before and after decorating. Adornment mode expands the functionality of an object without using the creation of more subclasses.
The class diagram for the decorating mode is as follows:
The roles in the decorating mode are:
abstract Component (Component) role: An abstract interface is given to standardize the objects that are ready to receive additional responsibilities.
Concrete Component (concretecomponent) Role: defines a class that will receive additional responsibilities.
decoration (Decorator) Role: holds an instance of a component (Component) object and defines an interface that is consistent with the abstract component interface.
specific decoration (concreteDecorator) Role: responsible for attaching the Component object "affixed" to the responsibility.
Source
Abstract component Roles
Public interface Component {public void sampleoperation (); }
Specific component roles
public class Concretecomponent implements Component { @Override public void Sampleoperation () { //write related business code }}
Decorative characters
public class Decorator implements component{ private Component Component; Public Decorator (Component Component) { this.component = Component; } @Override public void Sampleoperation () { //delegated to Widget component.sampleoperation (); } }
Specific decorative characters
public class Concretedecoratora extends Decorator {public Concretedecoratora (Component Component) { super ( component); } @Override public void Sampleoperation () {
Super.sampleoperation (); Write the relevant business code }}
public class Concretedecoratorb extends Decorator {public concretedecoratorb (Component Component) { super ( component); } @Override public void Sampleoperation () {
Super.sampleoperation (); Write the relevant business code }}
The example of the Holy Grail
There are 72 changes in the Sun Wukong, and each of his changes brings him an additional skill. When he becomes a fish, he can swim in the water, and when he becomes a bird, he can fly in the sky.
In this case, component's role is played by the famous concretecomponent, the role of which belongs to the Holy Buddha, Hozen himself, and decorator's role is played by the 72. And Concretedecorator's role is 72 changes like fish, birds and so on.
Source
Abstract component role the "Franzia-san" interface defines a move () method, which must be implemented by all concrete component classes and adornment classes.
The Zunhao public interface Thegreatestsage {public void move ();
Concrete component Role "The Holy Buddha" Hozen class
public class Monkey implements Thegreatestsage { @Override public void Move () { //code System.out.println ("Monkey Move");} }
Abstract decorative Character "72 change"
public class Change implements Thegreatestsage { private thegreatestsage sage; Public change (Thegreatestsage Sage) { this.sage = sage; } @Override public void Move () { //code Sage.move ();} }
Specific decorative characters "fish"
public class Fish extends change {public Fish (Thegreatestsage Sage) { super (SAGE); } @Override public void Move () { //code SYSTEM.OUT.PRINTLN ("Fish move"); }
Specific decorative characters "birds"
public class Bird extends change {public Bird (Thegreatestsage Sage) { super (SAGE); } @Override public void Move () { //code SYSTEM.OUT.PRINTLN ("Bird move");} }
Client class
public class Client {public static void Main (string[] args) { thegreatestsage sage = new Monkey (); The first form of thegreatestsage bird = new Bird (sage); Thegreatestsage fish = new Fish (bird); The second notation //thegreatestsage fish = new Fish (new Bird (sage)); Fish.move (); }}
"The Holy Buddha" is the Concretecomponent class, while the "Bird", "fish" is a decorative category. To decorate is "the Holy Buddha", also known as "Hozen" example.
In the above example, the system decorated the holy Man from a hozen into a bird (the function of the birds added to the Hozen body), and then decorate the birds into a fish (the function of the fish added to the Hozen + birds, got Hozen + birds + fish).
As shown, the change of the sage first attaches the function of the bird to the Hozen body, and then attaches the function of the fish to the Hozen + bird.
Simplification of decoration modes
In most cases, the implementation of the decoration pattern is simpler than the illustrative example given above.
If there is only one Concretecomponent class, you can consider removing the abstract component Class (interface) and decorator as a concretecomponent subclass. As shown in the following:
If there is only one Concretedecorator class, then there is no need to create a separate decorator class, but you can combine the responsibilities of decorator and Concretedecorator into a single class. This can be done even in the case of only two concretedecorator classes. As shown in the following:
Requirements for transparency
The transparency of the decorative mode to the client requires the program not to declare a variable of type concretecomponent, but to declare a variable of type component.
In the case of Monkey King, we must always treat all the changes of the Sun Wukong as the Monkey King, and if the old sun turns into a fish as a fish, instead of the old sun, it will be cheated by the old sun, and this should not happen. The following is the right approach:
Thegreatestsage sage = new Monkey (); Thegreatestsage bird = new Bird (SAGE);
And the following is not the right approach:
Monkey sage = new Monkey (); Bird Bird = new Bird (SAGE);
Semi-transparent decorative pattern
However, purely decorative patterns are difficult to find. The decoration mode is intended to enhance the performance of the class under consideration without changing the interface. When it comes to enhancing performance, it's often necessary to create new, public methods. Even in Bajau systems, new methods are needed. For example, the Grand Saint class does not have the ability to fly, and the birds have. This means that the bird should have a new fly () method. For example, the Grand Saint class does not have the ability to swim, and fish have, which means there should be a new swim () method in the Fish class.
This led to the realization of most of the decorative patterns being "translucent" rather than completely transparent. In other words, allow the decoration mode to change the interface and add new methods. This means that the client can declare a variable of type concretedecorator so that it can invoke a method in the Concretedecorator class:
Thegreatestsage sage = new Monkey (); Bird Bird = new Bird (sage); Bird.fly ();
The translucent decoration mode is between the decoration mode and the adapter mode. The intent of the adapter pattern is to change the interface of the class being considered, or by rewriting one or more methods, or by adding new methods to enhance or change the functionality of the class being considered. Most of the decorative patterns are actually translucent decorative patterns, which are also known as semi-decorative, half-adapter modes.
Advantages of Decorative Mode
(1) The purpose of the adornment mode and the inheritance relation is to extend the function of the object, but the adornment mode can provide more flexibility than the inheritance. Decoration mode allows the system to dynamically decide to "paste" a desired "decoration", or to remove an unwanted "decoration". The inheritance relation is different, the inheritance relation is static, it decides before the system runs.
(2) Designers can create a combination of many different behaviors by using different decorative classes and arranging combinations of these decorations.
Disadvantages of Decoration mode
Because of the use of adornment mode, a smaller number of destination classes are required than using inheritance relationships. The use of fewer classes, of course, makes the design easier to carry out. However, on the other hand, using the adornment pattern produces more objects than using the inheritance relationship. More objects make it difficult to find errors, especially when they look alike.
Application of design Patterns in the Java I/O library
The most famous application of decorating patterns in the Java language is the design of the Java I/O standard library.
Because the Java I/O library requires a variety of combinations of performance, if these performance are implemented in an inherited way, then each combination requires a class, which results in a large number of performance-repeating classes appearing. In the case of decorative patterns, the number of classes is greatly reduced, and the repetition of performance can be minimized. Therefore, the decoration mode is the basic mode of the Java I/O library.
The object structure diagram for the Java I/O library is as follows, because of the large number of Java I/O objects, only the InputStream part is drawn.
As you can see:
abstract Component (Component) role: played by InputStream. This is an abstract class that provides a unified interface for each seed type.
specific component (concretecomponent) roles: Bytearrayinputstream, FileInputStream, PipedInputStream, StringBufferInputStream and other class play. They implement the interfaces specified by the abstract component role.
abstract Decoration (Decorator) role: played by FilterInputStream. It implements the interface specified by the InputStream.
specific decoration (concretedecorator) role: played by several classes, namely Bufferedinputstream, DataInputStream and two infrequently used classes Linenumberinputstream, Pushbackinputstream.
Semi-transparent decorative pattern
Both the adornment mode and the adapter mode are "wrapper mode (Wrapper pattern)", which are designed to encapsulate other objects, but their morphology is very different.
The ideal decoration mode is to enhance the function of the decorative object, and it requires the interface of the concrete component role and the decorative role to be identical with the interface of the abstract component role. The adapter mode is not, in general, the adapter pattern does not require enhancements to the source object's functionality, but it alters the interface of the source object to match the target interface.
The decorative mode is transparent and translucent, the difference between the interface of the decorative role and the interface of the abstract component role is exactly the same. The transparent decoration mode is the ideal decoration mode, which requires the interface of the specific component role and the decorative role to be identical to the interface of the abstract component role. Conversely, if the interface of the adornment role is inconsistent with the abstract component role interface, which means that the interface of the decorative role is wider than the interface of the abstract component role, the decorative role is actually an adapter role, and this adornment pattern is also acceptable, known as the "translucent" decorative pattern, as shown in.
In adapter mode, the interface of an adapter class usually overlaps with the interface of the target class, but it is often not identical. In other words, the interface of the adapter class is wider than the target class interface being decorated.
Obviously, the translucent decorative pattern is actually the gray area between the adapter mode and the decorative mode. If the adornment mode and the adapter mode are merged into a "wrapping mode", then the translucent decoration mode can become the representative of this merged "packing mode".
Decorative modes in the InputStream type
The adornment mode in the InputStream type is translucent. To illustrate this, take a look at the source code for the InputStream of the abstract component role as a decorative pattern. This abstract class declares nine methods and gives the implementation of eight of them, and the other is an abstract method that needs to be implemented by a subclass.
Public abstract class InputStream implements closeable {public abstract int read () throws IOException; public int read (byte b[]) throws IOException {} public int read (byte b[], int off, int len) throws IOException {} Public long Skip (long N) throws IOException {} public int available () throws IOException {} public void close () th Rows IOException {} public synchronized void Mark (Int. readlimit) {} public synchronized void Reset () throws Ioexce ption {} public Boolean marksupported () {}}
The following is the source code for the FilterInputStream class as an abstract decorative role in decorative mode. As you can see, the FilterInputStream interface is exactly the same as the InputStream interface. That is, until this step, it is still in accordance with the decorative pattern.
public class FilterInputStream extends InputStream { protected FilterInputStream (InputStream on) {} public int Read () throws IOException {} public int read (byte b[]) throws IOException {} public int read (byte b[], int off, in T len) throws IOException {} public long Skip (long N) throws IOException {} public int available () throws Ioexcept Ion {} public void Close () throws IOException {} public synchronized void Mark (Int. readlimit) {} public SYNCHR onized void Reset () throws IOException {} public Boolean marksupported () {}}
The following is the source code for the specific decorative role pushbackinputstream.
public class Pushbackinputstream extends FilterInputStream { private void Ensureopen () throws IOException {} Public Pushbackinputstream (InputStream in, int size) {} public Pushbackinputstream (InputStream in) {} Public int read () throws IOException {} public int read (byte[] B, int. off, int len) throws IOException {} public void UNR EAD (int b) throws IOException {} public void unread (byte[] B, int. off, int len) throws IOException {} public void Unread (byte[] b) throws IOException {} public int available () throws IOException {} public long Skip (long N) throw S IOException {} public Boolean marksupported () {} public synchronized void Mark (Int. readlimit) {} Public synchronized void Reset () throws IOException {} public synchronized void Close () throws IOException {}}
Looking at the source code, you will find that this decoration class provides an additional method of unread (), which means that pushbackinputstream is a translucent decoration class. In other words, it destroys the ideal decorative pattern of the requirements. If the client holds a reference to a type InputStream object, then if the real type of in is Pushbackinputstream, then the client is generally no problem as long as the client does not need to use the unread () method. However, if the client must use this method, the downward type conversion must be performed. This method may not be called until the type of in has been converted to Pushbackinputstream. However, this type conversion means that the client must know that the reference it gets is pointing to an object of type Pushbackinputstream. This undermines the original intent to use the decorative pattern.
There is a gap between the real world and the theory. Purely decorative patterns are hard to find in real systems. In general, it is this translucent decorative pattern.
The following is a simple example of how to read the contents of a file using I/O streams.
public class Iotest {public static void Main (string[] args) throws IOException { //stream Read file datainputstream di s = null; try{ New DataInputStream (New Bufferedinputstream (New fileinputstream ("test.txt" )); //Read file contents byte[] bs = new byte[dis.available ()]; Dis.read (BS); String content = new String (BS); SYSTEM.OUT.PRINTLN (content); } finally{ dis.close ();}}}
Observing the above code, you will find the innermost layer is a FileInputStream object, and then pass it to a Bufferedinputstream object, after Bufferedinputstream processing, Then the processed object is passed to the DataInputStream object for processing, this process is actually the decorator assembly process, the FileInputStream object is equivalent to the original decorated object, Bufferedinputstream objects and DataInputStream objects are the equivalent of adorners.
The decorative pattern of Java and pattern