設計模式-----裝飾模式

裝飾模式

個人博客,想要搭建個人博客的可以進來看看: http://www.ioqian.top/


裝飾模式,動態的將責任附加到對象上。若要擴展功能,裝飾者提供了比繼承更有彈性的替代方案,在Java JDK的io實現中使用了大量的裝飾者模式

設計模式系列博客博主源碼: https://github.com/liloqian/DesiginModeDemo

背景
我們要幫星巴克提供一個自動打印咖啡信息和價格的軟件,比如基礎的濃縮咖啡,混合咖啡,每個基礎咖啡加了什麼調料(幾分糖,幾分牛奶等等)。如果我們對每種咖啡具體實現,這簡直是類爆炸,每個人有自己的咖啡配料方式,要寫幾萬個類… 我們這裏要是有裝飾模式

我們先來看一下裝飾者模式的UML

通過我們的背景來生動的描述

結合UML和我們的模擬場景說明一下

  • Component 公共父類,這裏就是我們的咖啡父類,下面的調料和基本咖啡類型都要繼承Component
  • ConcreteComponent 被裝飾者,相當於我們的基本咖啡類型我們有兩種
  • Decorator,裝飾者 ,相當於調料接口,這個接口的任意實現都可以包裝咖啡父類的實現者,我這裏也用了接口
  • ConcreateDecoratorA ,這裏相當於上圖右下角的牛奶加糖的濃縮咖啡,一個裝飾例子

裝飾者模式的特點
- 裝飾者和被裝飾者有共同的超類型
- 裝飾對象包含一個真實對象的引用
- 可以用多個裝飾對象包裝一個被裝飾對象
- 對象可以在任何時候被裝飾

下面來看代碼實現,就是上面我們的模擬情景
公共父類的實現

//裝飾者和被裝飾者的公共父類
public abstract class Beverage {
    //父類狀態描述
    String description = "Base Beverage";
    //具體的價格讓基本咖啡類型加上裝飾者的價格確定
    public abstract double cost();
    public String getDescription() {
        return description;
    }
}

兩種基本咖啡類型,濃縮咖啡和混合咖啡
濃縮咖啡

//濃縮咖啡類型 ,繼承了父類
public class Espresso extends Beverage {
    public Espresso() {
        description = "Espresso coffee";
    }
    //濃縮咖啡的價格
    @Override
    public double cost() {
        return 1.9;
    }
}

混合咖啡

//混合咖啡
public class Blend extends Beverage {
    public Blend() {
        description = "Blend coffee";
    }
    //混合咖啡價格
    @Override
    public double cost() {
        return 2.9;
    }
}

調料接口

//調料接口,和基本咖啡類型有共同的父類
public abstract class Spices extends Beverage {
    public abstract String getDescription();
}

調料糖

public class Sugar extends Spices {
    Beverage beverage;
    //我們用父類,不要基本的咖啡類型
    public Sugar(Beverage beverage) {
        this.beverage = beverage;
    }
    //修飾咖啡名稱狀態, 修飾屬性+基本屬性
    @Override
    public String getDescription() {
        return "Sugar " + beverage.getDescription();
    }
    //修飾咖啡價格  糖的價格加上自身本來價格
    @Override
    public double cost() {
        return .5 + beverage.cost();
    }
}

調料牛奶,和上面類似

public class Milk extends Spices {
    Beverage beverage;
    public Milk(Beverage beverage) {
        this.beverage = beverage;
    }
    @Override
    public double cost() {
        return 0.3 + beverage.cost();
    }
    @Override
    public String getDescription() {
        return "Milk "+beverage.getDescription();
    }
}

main測試

public class Main {
    public static void main(String[] args) {
        //普通的混合咖啡
        Beverage blend = new Blend();
        printInfo(blend);
        //加了一份牛奶的混合咖啡
        Beverage blendMilk = new Milk(blend);
        printInfo(blendMilk);
        //加了2份糖的一份牛奶的混合咖啡
        Beverage blendMilkSugarTwo = new Sugar(new Sugar(blendMilk));
        printInfo(blendMilkSugarTwo);
        //加了一份糖一份牛奶的濃縮咖啡
        Beverage espresson = new Sugar(new Milk(new Espresso()));
        printInfo(espresson);
    }
    //提取打印咖啡的打印方法
    private static void printInfo(Beverage beverage){
        System.out.println(beverage.getDescription() +"   價格:"+beverage.cost());
    }
}
結果
Blend coffee   價格:2.9
Milk Blend coffee   價格:3.1999999999999997
Sugar Sugar Milk Blend coffee   價格:4.199999999999999
Sugar Milk Espresso coffee   價格:2.6999999999999997

Process finished with exit code 0

裝飾者模式用到的設計原則

開閉原則對擴展開發,對修改關閉原則 , 沒有太多的感悟,在後面的源碼中尋找想法,歡迎大神用通俗的話語概況

發佈了75 篇原創文章 · 獲贊 18 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章