Decorator mode

Posted by sheckel on Tue, 11 Jan 2022 02:07:26 +0100

Structure and implementation of decorator mode

Usually, the function of extending a class is implemented by inheritance. However, inheritance has static characteristics, high coupling, and subclasses will expand with the increase of extended functions. The goal of decorator pattern is to create a wrapper object (i.e. decoration object) to wrap the real object and provide it with additional functions on the premise of keeping the class structure of the real object unchanged. The basic structure and implementation method are analyzed below.

1. Structure of the model

Decorator mode mainly includes the following roles.

  1. Abstract Component role: define an abstract interface to standardize objects ready to receive additional responsibilities.
  2. Concrete component role: implement abstract components and add some responsibilities to them by decorating roles.
  3. Abstract Decorator role: inherits abstract components and contains instances of specific components. You can extend the functions of specific components through its subclasses.
  4. Concrete decorator role: implement relevant methods of abstract decoration and add additional responsibilities to specific component objects.


The structure diagram of the decorator mode is shown in Figure 1.
 


Fig. 1 structure diagram of decorator mode

2. Implementation of mode

The implementation code of decorator 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 role
class ConcreteComponent implements Component {
    public ConcreteComponent() {
        System.out.println("Create concrete component roles");
    }

    public void operation() {
        System.out.println("Calling methods for 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 functions to specific component roles addedFunction()");
    }
}

The running results of the program are as follows:

Create concrete component roles
 Call the method operation() of the specific component role
---------------------------------
Call the method operation() of the specific component role
 Add additional functions for specific component roles addedFunction()

Application example of decorator mode

[example 1] realize the transformation of the game character "Monica anslan" in the decorator mode.

Analysis: in demon warrior, the original body of the game character "Monica anslan" is a lovely girl, but when she changes, she will become a banshee with bat like wings extending from her head and back. Of course, she can also become a girl wearing a beautiful coat. These can be realized by decorator mode. In this example, the original body of "molika" has setImage(String t) method to determine its display mode, while its transformed "bat Banshee" and "dressed girl" can change their appearance with setchange() method, and the effects behind the original body and transformation are displayed with display() method( Click here to download the original and transformed pictures )Fig. 2 shows its structure.
 


Figure 2 structure diagram of the game character "molika anslan"


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: Monica
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("<Monica in demon Warrior·Ansland");
    }

    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 characters: 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 program running results are shown in Figure 3.
 


Figure 3 Transformation of the game character "molika anslan"

Application scenario of decorator mode

The structure and characteristics of the decorator mode were explained earlier. The applicable application scenarios are introduced below. The decorator mode is usually used in the following situations.

  • When you need to add additional responsibilities to an existing class, but you can't expand it by generating subclasses. For example, if the class is hidden, or the class is the ultimate class, or inheritance will produce a large number of subclasses.
  • When it is necessary to arrange and combine a set of existing basic functions to produce a lot of functions, it is difficult to realize it by using inheritance relationship, but it is easy to realize it by using decorator mode.
  • When the functional requirements of an object can be added or revoked dynamically.


Decorator mode in Java The most famous application in the 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 abstract decoration classes.

 

 

Topics: Design Pattern