1. 程式人生 > 其它 >java23種設計模式之十一:裝飾者模式

java23種設計模式之十一:裝飾者模式

一.應用場景

如果你在遇到需要動態的給一個物件增加新的屬性(變數)和行為(方法),而這些屬性和行為又在一個獨立的類中,那麼,你可以瞭解一下裝飾者模式。

優點:可以更方便、更靈活的為一個物件動態的增加功能和屬性,如果用生成子類的方法,會造成類膨脹

並且還會產生很多冗餘程式碼。

缺點:需要你細細體會和深入瞭解

二.名詞解釋

1.Component(主體類:被裝飾物件的基類)

定義一個抽象類或介面,定義一些屬性和行為

2.ConcreteComponent(主體實現類:具體被裝飾物件)

定義一個類,繼承或實現主體類中的屬性和行為。

3.Decorator(裝飾類)

定義一個裝飾者類,新增一個主體類的屬性,並實現或定義一個與主體類介面一致的介面。

4.ConcreteDecorator(裝飾實現類1)

定義一個類,繼承裝飾者類,可以在內部封裝具體的屬性和行為,增加具體的功能。

三.需求

我想喝一杯飲料:

1.一杯咖啡,可以加牛奶、加巧克力

2.一杯奶茶,可以加牛奶、加巧克力

四.UML類圖

  

五.示例

1.主體類

package com.zpb.decorate;

/**
 * @author       pengbo.zhao
 * @description  飲品-被裝飾類
 * @createDate   2021/9/27 10:28
 * @updateDate   2021/9/27 10:28
 * @version      1.0
 
*/ public abstract class AbstractDrink { /** * 飲品名稱 */ public String name; /** * 飲品價格 */ public float price; /** * 飲品描述 */ public String description; /** * 花費多少錢 * @return float */ public abstract float cost(); public String getName() {
return name; } public void setName(String name) { this.name = name; } 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; } }

2.主體實現類

package com.zpb.decorate;

/**
 * @author       pengbo.zhao
 * @description  咖啡-單品
 * @createDate   2021/9/27 10:31
 * @updateDate   2021/9/27 10:31
 * @version      1.0
 */

public class Coffee extends AbstractDrink {

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

    @Override
    public String getDescription() {
        return description + " 消費:" + cost() + "元";

    }

}

3.裝飾類

package com.zpb.decorate;

/**
 * @author       pengbo.zhao
 * @description  裝飾者-飲品
 * @createDate   2021/9/27 10:35
 * @updateDate   2021/9/27 10:35
 * @version      1.0
 */

public class DecoratorDrink extends AbstractDrink {

    public final AbstractDrink drink;

    public DecoratorDrink(AbstractDrink drink) {
        this.drink = drink;
    }

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

    @Override
    public String getDescription() {
        return description + " 消費:" + cost()+ "元";
    }

}

4.裝飾類實現一

package com.zpb.decorate;

/**
 * @author       pengbo.zhao
 * @description  巧克力
 * @createDate   2021/9/28 10:25
 * @updateDate   2021/9/28 10:25
 * @version      1.0
 */

public class Chocolate extends DecoratorDrink{

    public Chocolate(AbstractDrink drink) {
        super(drink);
        setName("巧克力");
        setPrice(5.0f);
    }

}

5.裝飾類實現二

package com.zpb.decorate;

/**
 * @author       pengbo.zhao
 * @description  牛奶咖啡
 * @createDate   2021/9/27 11:36
 * @updateDate   2021/9/27 11:36
 * @version      1.0
 */

public class MilkCoffee extends DecoratorDrink {

    public MilkCoffee(AbstractDrink drink) {
        super(drink);
    }

}

6.測試類

package com.zpb.decorate;

/**
 * @author       pengbo.zhao
 * @description  咖啡-測試類
 * @createDate   2021/9/27 11:40
 * @updateDate   2021/9/27 11:40
 * @version      1.0
 */

public class CoffeeTest {

    public static void main(String[] args) {

        // 咖啡單品
        Coffee coffee = new Coffee();
        coffee.setName("咖啡");
        coffee.setPrice(10.f);
        coffee.setDescription("單品咖啡");
        System.err.println(coffee.getDescription());

        // 咖啡 + 牛奶
        MilkCoffee milkCoffee = new MilkCoffee(coffee);
        milkCoffee.setName("牛奶");
        milkCoffee.setPrice(3.0f);
        milkCoffee.setDescription("單品咖啡 + 牛奶");
        System.err.println(milkCoffee.getDescription());

        // 咖啡 + 牛奶 + 巧克力
        Chocolate chocolate = new Chocolate(milkCoffee);
        chocolate.setName("巧克力");
        chocolate.setPrice(5.0f);
        chocolate.setDescription("單品咖啡 + 牛奶 + 巧克力");

        System.err.println(chocolate.getDescription());

        
    }

}

// 輸出結果
// 單品咖啡 消費:10.0元
// 單品咖啡 + 牛奶 消費:13.0元
// 單品咖啡 + 牛奶 + 巧克力 消費:18.0元

六.總結

通過示例,我們通過咖啡這個單品,來不斷增加咖啡這個類的屬性,當然,我們也可以通過產生新的主體實現類,通過已有的裝飾者實現類來增強屬性。

由於本人是自己學習總結出來的,有不足之處,請各位看官批評指出,我將及時改正,以提高知識總結的正確性和嚴謹性,為大家學習提供方便!!! 如若轉載,請註明出處!!!