Design pattern learning 10 (Java implementation) – Decorator Pattern

Time:2021-6-30

Write on the front

  • Take notes on learning design patterns
  • Improve the flexible use of design patterns

Learning address

https://www.bilibili.com/video/BV1G4411c7N4

https://www.bilibili.com/video/BV1Np4y1z7BU

Reference article

http://c.biancheng.net/view/1317.html

Project source code
https://gitee.com/zhuang-kang/DesignPattern

12. Decorator mode

12.1 definition and characteristics of Decorator Pattern

Definition of decorator mode:It refers to the mode of dynamically adding some responsibilities (i.e. adding additional functions) to the object without changing the existing object structureIt belongs to the object structure pattern.

The main advantages of decorator mode are as follows:

  • Decorator is a powerful supplement to inheritance, which is more flexible than inheritance. It can dynamically extend the function of an object, plug and play, without changing the original object
  • Different effects can be achieved by using different decoration classes and the arrangement and combination of these decoration classes
  • The decorator mode fully follows the principle of opening and closing

The main disadvantages are as follows

  • Decorator pattern will add many subclasses, overuse will increase the complexity of the program.

12.2 structure and implementation of decorator mode

Generally, the function of extending a class is implemented by inheritance. However, inheritance has static characteristics, high coupling degree, and with the increase of extended functions, subclasses will expand. The goal of decorator pattern is to create a wrapper object (i.e. decoration object) to wrap the real object and provide additional functions for the real object while keeping the class structure of the real object unchanged

12.2.1 structure of Decorator Pattern

  1. Abstract component role: define an abstract interface to specify the object that is ready to receive additional responsibilities.
  2. Concrete component role: realize abstract component and add some responsibilities for it by decorating role.
  3. Abstract decorator role: inherits abstract components and contains instances of concrete components, and can extend the functions of concrete components through its subclasses.
  4. Concrete decorator role: implement the relevant methods of abstract decoration and add additional responsibilities to concrete component objects.

12.2.2 code implementation

Relationship class diagram

Design pattern learning 10 (Java implementation) - Decorator Pattern

Fastfood abstract component role

package com.zhuang.decorator;

/**
 * @Classname FastFood
 *@ description class interface
 * @Date 2021/3/23 21:54
 * @Created by dell
 */

public abstract class FastFood {
    private float price;
    private String desc; // describe

    public FastFood() {
    }

    public FastFood(float price, String desc) {
        this.price = price;
        this.desc = desc;
    }

    public float getPrice() {
        return price;
    }

    public void setPrice(float price) {
        this.price = price;
    }

    public String getDesc() {
        return desc;
    }

    public void setDesc(String desc) {
        this.desc = desc;
    }

    //Abstract method to get price
    public abstract float cost();
}

The role of firedrice

package com.zhuang.decorator;

/**
 * @Classname FiredRice
 *@ description fried rice inherits fast food
 * @Date 2021/3/23 21:54
 * @Created by dell
 */

public class FiredRice extends FastFood {

    public FiredRice() {
        Super (10, "fried rice");
    }

    @Override
    public float cost() {
        return getPrice();
    }

}

The role of firednoodles

package com.zhuang.decorator;

/**
 * @Classname FiredNoodles
 *@ description fried noodles inherit fast food
 * @Date 2021/3/23 21:54
 * @Created by dell
 */

public class FiredNoodles extends FastFood {

    public FiredNoodles() {
        Super (15, "fried noodles");
    }

    @Override
    public float cost() {
        return getPrice();
    }
}

Garnish the abstract character

package com.zhuang.decorator;

/**
 * @Classname Garnish
 *@ description Abstract ingredient class inherits fast food class
 * @Date 2021/3/23 21:58
 * @Created by dell
 */

public abstract class Garnish extends FastFood{
    private FastFood fastFood;

    public FastFood getFastFood() {
        return fastFood;
    }

    public void setFastFood(FastFood fastFood) {
        this.fastFood = fastFood;
    }

    public Garnish(FastFood fastFood,float price,String desc){
        super(price,desc);
        this.fastFood = fastFood;
    }
}

Eggspecific decoration role

package com.zhuang.decorator;

/**
 * @Classname Egg
 *@ description egg ingredient class inherits the ingredient class
 * @Date 2021/3/23 21:55
 * @Created by dell
 */

public class Egg extends Garnish {

    public Egg(FastFood fastFood) {
        //Egg 1 yuan
        Super (fastfood, 1, "egg");
    }

    @Override
    public float cost() {
        return getPrice() + getFastFood().getPrice();
    }

    @Override
    public String getDesc() {
        return super.getDesc() + getFastFood().getDesc();
    }
}

The specific role of bacon

package com.zhuang.decorator;

/**
 * @Classname Bacon
 *The @ description bacon class inherits the ingredient class
 * @Date 2021/3/23 22:03
 * @Created by dell
 */

public class Bacon extends Garnish {

    public Bacon(FastFood fastFood) {
        //Bacon 2 yuan
        Super (fastfood, 2, "Bacon");
    }

    @Override
    public float cost() {
        return getPrice() + getFastFood().getPrice();
    }

    @Override
    public String getDesc() {
        return super.getDesc() + getFastFood().getDesc();
    }
}

Client

package com.zhuang.decorator;

/**
 * @Classname Client
 *@ description decorator pattern test class
 * @Date 2021/3/23 21:53
 * @Created by dell
 */

public class Client {
    public static void main(String[] args) {
        //Order fried rice
        FastFood rice = new FiredRice();
        //Price
        System. Out. Println (rice. Getdesc() + "-- >" + rice. Cost() + "Yuan");

        System.out.println("=============================");

        //Order fried rice with eggs
        FastFood eggRice = new FiredRice();
        //Add eggs
        eggRice = new Egg(eggRice);
        System. Out. Println (eggrice. Getdesc() + "-- >" + eggrice. Cost() + "Yuan");

        System.out.println("=============================");

        //Order fried noodles with bacon
        FastFood baconNoodles = new FiredNoodles();
        //Bacon
        baconNoodles = new Bacon(baconNoodles);
        System. Out. Println (baconoods. Getdesc() + "-- >" + baconoods. Cost() + "Yuan");

    }
}

Design pattern learning 10 (Java implementation) - Decorator Pattern

12.3 application scenarios of decorator mode

  • When the system can not be extended by inheritance or inheritance is not conducive to system expansion and maintenance.

    There are two main types of cases in which inheritance cannot be used

    • The first is that there are a large number of independent extensions in the system. In order to support each combination, a large number of subclasses will be generated, which makes the number of subclasses increase explosively;
    • The second is because the class definition cannot be inherited (such as the final class)
  • Add responsibilities to a single object in a dynamic and transparent way without affecting other objects.
  • When the functional requirements of an object can be added or withdrawn dynamically.

12.4 JDK source code analysis

The wrapper class in io stream uses decorator mode. BufferedInputStream,BufferedOutputStream,BufferedReader,BufferedWriter。

Let’s take the bufferedwriter as an example. First, let’s see how to use the bufferedwriter

public class Demo {
    public static void main(String[] args) throws Exception{
        //Create bufferedwriter object
        //Creating a filewriter object
        FileWriter fw = new FileWriter("C:\\Users\\dell\\Desktop\\a.txt");
        BufferedWriter bw = new BufferedWriter(fw);

        //Write data
        bw.write("hello Buffered");

        bw.close();
    }
}

structure

Design pattern learning 10 (Java implementation) - Decorator Pattern

Bufferedwriter uses decorator mode to enhance the writer subclass, and adds buffer to improve the efficiency of writing data.

The differences between static agent and decorator mode are as follows

  • Similarities:

    • To achieve the same business interface as the target class
    • Declare the target object in both classes
    • Can enhance the target method without modifying the target class
  • difference:

    • The purpose of different decorators is to enhance the target object, and the static proxy is to protect and hide the target object
    • Different decorators are passed in from the outside. Static proxies are created inside the proxy class to hide the target object

Write at the end

  • If my article is useful to you, please give me some, thank you!
  • If you have any questions, please point them out in the comments area!