Decorator mode of design mode

Posted by jack_ on Wed, 09 Feb 2022 20:07:32 +0100

Decorator mode

preface

  • I am a junior undergraduate majoring in software engineering. At present, we are preparing for internship and autumn recruitment. The intended position is java back-end development engineer. To this end, I hosted a project in codecloud to sort out all my knowledge. Contents involved: computer network, operating system, Java foundation, mainstream Java back-end framework, design pattern, Web front-end framework, etc. Welcome to my open source project The way of programming
  • Code cloud address: https://gitee.com/alizipeng/the-way-of-programming
  • The following contents are recorded in my open source project

1. Definitions

  • Dynamically attaching new functions to objects is decorator mode.

  • It embodies the opening and closing principle of the seven principles [OCP principle].

  • More extensible than inheritance.

2. Scene setting

Starbucks Coffee order project [Cafe]:

  1. Coffee type / single product: Espresso, ShortBlack, LongBlack, Decaf
  2. Seasoning: Milk, Soy Milk, Chocolate
  3. It is required to have good expansibility and maintainability when expanding new coffee varieties.
  4. Use object-oriented to calculate the cost of different kinds of coffee: customers can order single coffee or single coffee + seasoning combination.

3. Class structure design

3.1 Drink abstract class

/**
 * Beverage abstract class
 *
 * @author: zipeng Li
 * 2021/5/16  21:53
 */
public abstract class Drink {
    /**
     * Beverage description
     */
    private String description;
    /**
     * Price
     */
    private Float price;

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public Float getPrice() {
        return price;
    }

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

    /**
     * Calculate cost
     * @return
     */
    public abstract Float cost();
}

3.2 Coffee class

/**
 * @author: zipeng Li
 * 2021/5/16  22:17
 */
public class Coffee extends Drink {
    @Override
    public Float cost() {
        return super.getPrice();
    }
}

3.3 Decorator class

/**
 * Decorator
 *
 * @author: zipeng Li
 * 2021/5/16  22:41
 */
public class Decorator extends Drink {
    Drink drink;

    public Decorator(Drink drink) {
        this.drink = drink;
    }

    @Override
    public Float cost() {
        return getPrice() + drink.cost();
    }

    @Override
    public String getDescription() {
        return super.getDescription() + " Price:" + super.getPrice() + " && " + drink.getDescription();
    }
}

3.4 specific single coffee

Just list one of them, and other specific single coffee categories are similar.

/**
 * @author: zipeng Li
 * 2021/5/16  22:36
 */
public class Decaf extends Coffee {
    public Decaf() {
        setDescription("decaf Price: 2.0");
        setPrice(2.0f);
    }
}

3.5 specific seasoning categories

Only one of them is listed, and other specific seasoning categories are similar.

/**
 * @author: zipeng Li
 * 2021/5/17  7:21
 */
public class Chocolate extends Decorator {
    public Chocolate(Drink drink) {
        super(drink);
        setDescription("chocolate");
        setPrice(1.0f);
    }
}

3.6 test functional integrity

/**
 * @author: zipeng Li
 * 2021/5/17  7:23
 */
public class Test {
    public static void main(String[] args) {
        // Start order
        // 1. Order a ShortBlack
        Drink drink = new ShortBlack();
        System.out.println("Order Description:" + drink.getDescription());
        System.out.println("Total cost:" + drink.cost());
        // 2. Add a chocolate
        drink = new Chocolate(drink);
        System.out.println("Order Description:" + drink.getDescription());
        System.out.println("Total cost:" + drink.cost());
        // 3. Add two copies of soy
        drink = new Soy(drink);
        drink = new Soy(drink);
        System.out.println("Order Description:" + drink.getDescription());
        System.out.println("Total cost:" + drink.cost());
    }
}

3.7 test scalability

Add a single coffee

/**
 * @author: zipeng Li
 * 2021/5/17  7:51
 */
public class DIYCoffee extends Coffee {
    public DIYCoffee() {
        setDescription("DIYCoffee Price: 6.0");
        setPrice(6.0f);
    }
}

Order a DIYCoffee, the condiment remains the same

4. Application in JDK

In the IO system of Java, decorator mode is used:

  • InputStream is an abstract class waiting to be decorated. Equivalent to the Drink class
  • FileInputStream, StringBufferInputStream and ByteArrayInputStream are subclasses of InputStream, which are equivalent to specific single coffee classes
  • FilterInputStream is a Decorator, equivalent to the Decorator class
  • BufferInputStream, DataInputStream and LineNumberInputStream are specific decoration classes, which are equivalent to specific condiments

Topics: Java Design Pattern