In real life, it is often necessary to add new functions or beautify the appearance of existing products, such as house decoration, photos and photo frames. In the process of software development, sometimes you want to use some existing components. These components may only accomplish some core functions. But it can expand its function dynamically without changing its structure. All of these can be realized by decoration mode.
The definition and characteristics of decoration pattern
The definition of Decorator Pattern: refers to the pattern that dynamically adds some responsibilities (i.e. additional functions) to the object without changing the existing object structure. It belongs to the object structure pattern.
The main advantages of Decorator mode are as follows:
- It is more flexible to extend the function of objects by decoration mode than by inheritance mode.
- It can design many different specific decoration classes and create many combinations of different behaviors.
The main drawback is that the decoration mode adds many subclasses, and if overused, the program will become very complex.
The structure and Realization of decoration mode
In general, the function of extending a class is implemented by inheritance. However, inheritance has static characteristics and high coupling. With the increase of extended functions, subclasses will expand. The goal of decoration pattern is to create a wrapper object (i.e. decoration object) to wrap the real object by using composition relation, and to provide additional functions for the real object while keeping its class structure unchanged. Next, we will analyze its basic structure and implementation method.
1. Structure of mode
Decoration mode mainly includes the following roles.
- Abstract Component role: define an abstract interface to standardize the object ready to receive additional responsibilities.
- Concrete component role: implement abstract component and add some responsibilities for it by decorating role.
- The role of Decorator: inherits the abstract component and contains instances of the concrete component. The function of the concrete component can be extended through its subclasses.
- Concrete decorator role: implement the relevant methods of abstract decoration and add additional responsibilities to concrete component objects.
The structural diagram of the decoration mode is shown in Figure 1.
Figure 1 Structure of decoration mode
2. Implementation of the pattern
The implementation code of decoration mode is as follows:
package decorator; public class DecoratorPattern { public static void main(String[] args) { Component p=new ConcreteComponent(); p.operation(); System.out.println("---------------------------------"); Component d=new ConcreteDecorator(p); d.operation(); } } //Abstract component role interface Component { public void operation(); } //Specific component roles class ConcreteComponent implements Component { public ConcreteComponent() { System.out.println("Create specific component roles"); } public void operation() { System.out.println("Methods to call specific component roles operation()"); } } //Abstract decorative role class Decorator implements Component { private Component component; public Decorator(Component component) { this.component=component; } public void operation() { component.operation(); } } //Specific decorative role class ConcreteDecorator extends Decorator { public ConcreteDecorator(Component component) { super(component); } public void operation() { super.operation(); addedFunction(); } public void addedFunction() { System.out.println("Add additional functionality to specific component roles addedFunction()"); } }
The running results of the program are as follows:
Create specific component roles
Call the method operation() of the specific component role
Call the method operation() of the specific component role
Add additional function () for specific component role
Application example of decoration mode
[example 1] use the decoration mode to realize the transformation of the game character "Monica ansland".
Analysis: in devil warrior, the original body of the game character "Monica ansland" is a lovely girl, but when she changes, she will become a banshee with bat like wings on her head and back. Of course, she can also become a girl in a beautiful coat. All of these can be realized by decoration mode. In this example, the original body of "morika" has setImage(String t) method to determine its display mode, while its transformation into "bat shaped Banshee" and "dressed girl" can use setChanger() method to change its appearance. The original body and the effect after transformation are displayed by display(), and Figure 2 shows its structure diagram.
Figure 2 structure of the game character "Monica ansland"
The program code is as follows:
package decorator; import java.awt.*; import javax.swing.*; public class MorriganAensland { public static void main(String[] args) { Morrigan m0=new original(); m0.display(); Morrigan m1=new Succubus(m0); m1.display(); Morrigan m2=new Girl(m0); m2.display(); } } //Abstract component role: morika interface Morrigan { public void display(); } //Specific component role: Original class original extends JFrame implements Morrigan { private static final long serialVersionUID = 1L; private String t="Morrigan0.jpg"; public original() { super("<Mollika in devil warrior·An LAN"); } public void setImage(String t) { this.t=t; } public void display() { this.setLayout(new FlowLayout()); JLabel l1=new JLabel(new ImageIcon("src/decorator/"+t)); this.add(l1); this.pack(); this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); this.setVisible(true); } } //Abstract decorative character: deformation class Changer implements Morrigan { Morrigan m; public Changer(Morrigan m) { this.m=m; } public void display() { m.display(); } } //Specific decorative role: Banshee class Succubus extends Changer { public Succubus(Morrigan m) { super(m); } public void display() { setChanger(); super.display(); } public void setChanger() { ((original) super.m).setImage("Morrigan1.jpg"); } } //Specific decorative role: girl class Girl extends Changer { public Girl(Morrigan m) { super(m); } public void display() { setChanger(); super.display(); } public void setChanger() { ((original) super.m).setImage("Morrigan2.jpg"); } }
The running result of the program is shown in Figure 3.
Figure 3 the transformation of the game character "Monica ansland"
Application scenario of decoration mode
The structure and characteristics of the decoration mode are explained in the front, and the applicable application scenarios are introduced below. The decoration mode is usually used in the following situations.
- When you need to add additional responsibilities to an existing class, but you cannot extend it by generating subclasses. For example, if the class is hidden or the class is the ultimate class or inherits, a large number of subclasses will be generated.
- When a group of existing basic functions need to be arranged and combined to produce a lot of functions, it is difficult to achieve by using inheritance relationship, but it is very good to achieve by using decoration mode.
- When the functional requirements of an object can be added or revoked dynamically.
The most famous application of decoration pattern in Java language is the design of Java I/O standard library. For example, the subclass FilterInputStream of InputStream, the subclass FilterOutputStream of OutputStream, the subclass BufferedReader and FilterReader of Reader, and the subclass BufferedWriter, FilterWriter and PrintWriter of Writer are all abstract decoration classes.
The following code is an example of the decoration class BufferedReader used to add buffer for FileReader:
BufferedReader in=new BufferedReader(new FileReader("filename.txtn)); String s=in.readLine();
Extension of decoration mode
The four roles contained in the decoration mode do not exist at any time. In some application environments, the mode can be simplified, such as the following two cases.
(1) If there is only one concrete component but no abstract component, the abstract decoration can inherit the concrete component, and its structure diagram is shown in Figure 4.
Figure 4 decoration mode with only one specific component
(2) If there is only one concrete decoration, the abstract decoration and concrete decoration can be combined, and the structure diagram is shown in Figure 5.
Figure 5 decoration mode with only one specific decoration