這個男人帶着他的裝飾者模式來了!!!

今天給大家說一下23種設計模式中的第九種——裝飾者模式。一般的,我們爲了擴展一個類經常使用繼承方式實現,由於繼承爲類引入靜態特徵,並且隨着擴展功能的增多,子類會很膨脹。這個時候,我們就需要用到裝飾者模式了,它可以實現在不增加很多子類的情況下擴展類的功能。

概念:

裝飾者模式(Decorator Pattern)允許向一個現有的對象添加新的功能,同時又不改變其結構。這種類型的設計模式屬於結構型模式,它是作爲現有的類的一個包裝。這種模式創建了一個裝飾類,用來包裝原有的類,並在保持類方法簽名完整性的前提下,提供了額外的功能。

特點:

優點:

  • 採用裝飾者模式擴展對象的功能比採用繼承方式更加靈活。
  • 裝飾者模式可以設計出多個不同的具體裝飾類,創造出多個不同行爲的組合。

缺點:

  • 雖然裝飾者模式能夠動態地將責任附加到對象上,但是他會產生許多的細小對象,增加了系統的複雜度。
類圖分析:

image-20200408211335325

代碼:

Drink 飲品抽象類

package cn.ppdxzz.decorator;
/**
 * Description:Drink飲品抽象類
 *
 * @Date: 2020/4/8
 * @Author: PeiChen JavaAnything
 */
public abstract class Drink {
    private String description;//描述
    private float price = 0.0f;//價格

    //計算總價格的抽象方法
    public abstract float cost();

    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;
    }
}

咖啡緩衝類

package cn.ppdxzz.decorator;
/**
 * Description:咖啡類
 *
 * @Date: 2020/4/8
 * @Author: PeiChen JavaAnything
 */
public class Coffee extends Drink {
    @Override
    public float cost() {
        return super.getPrice();
    }
}

無因咖啡

package cn.ppdxzz.decorator;
/**
 * Description:無因咖啡
 *
 * @Date: 2020/4/8
 * @Author: PeiChen JavaAnything
 */
public class Decaf extends Coffee {
    public Decaf() {
        setDescription("無因咖啡");
        setPrice(2.0f);
    }
}

美式咖啡

package cn.ppdxzz.decorator;
/**
 * Description:美式咖啡
 *
 * @Date: 2020/4/8
 * @Author: PeiChen JavaAnything
 */
public class LongBlack extends Coffee {
    public LongBlack() {
        setDescription("美式咖啡");
        setPrice(3.0f);
    }
}

裝飾者類

package cn.ppdxzz.decorator;
/**
 * Description:裝飾者類
 *
 * @Date: 2020/4/8
 * @Author: PeiChen JavaAnything
 */
public class Decorator extends Drink {
    private Drink drink;

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

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

    @Override
    public String getDescription() {
        //drink.getDescription() 輸出被裝飾者的描述
        return super.getDescription() + ":" + super.getPrice() +"" + " + " + drink.getDescription();
    }
}

牛奶

package cn.ppdxzz.decorator;
/**
 * Description:牛奶
 *
 * @Date: 2020/4/8
 * @Author: PeiChen JavaAnything
 */
public class Milk extends Decorator {

    public Milk(Drink drink) {
        super(drink);
        setDescription("牛奶");
        setPrice(2.0f);
    }
}

巧克力

package cn.ppdxzz.decorator;
/**
 * Description:巧克力
 *
 * @Date: 2020/4/8
 * @Author: PeiChen JavaAnything
 */
public class Chocolate extends Decorator{
    public Chocolate(Drink drink) {
        super(drink);
        setDescription("巧克力");
        setPrice(2.0f);
    }
}

咖啡訂單

package cn.ppdxzz.decorator;
/**
 * Description:裝飾者模式咖啡訂單,無因咖啡+兩份牛奶+一份巧克力
 *
 * @Date: 2020/4/8
 * @Author: PeiChen JavaAnything
 */
public class CoffeeOrder {
    public static void main(String[] args) {
        //1.點一份無因咖啡
        Drink order = new Decaf();
        System.out.println("無因咖啡的費用:" + order.getPrice());
        System.out.println("無因咖啡的描述:" + order.getDescription());
        //2.加一份牛奶
        order = new Milk(order);
        System.out.println("訂單加入一份牛奶的費用:" + order.cost());
        System.out.println("訂單加入一份牛奶的描述:" + order.getDescription());
        order = new Milk(order);
        System.out.println("訂單加入兩份牛奶的費用:" + order.cost());
        System.out.println("訂單加入兩份牛奶的描述:" + order.getDescription());
        order = new Chocolate(order);
        System.out.println("訂單加入兩份牛奶和一份巧克力的費用:" + order.cost());
        System.out.println("訂單加入兩份牛奶和一份巧克力的描述:" + order.getDescription());

    }
}

運行結果:

image-20200408210427707

總結:
  • Java 的 IO 結構,FilterInputStream 就是一個裝飾者。
  • 裝飾類和被裝飾類可以獨立發展,不會相互耦合,裝飾模式是繼承的一個替代模式,裝飾模式可以動態擴展一個實現類的功能。
  • 裝飾模式增加了許多子類,如果過度使用會使程序變得很複雜。

微信公衆號,JavaAnything,期待你的關注!
JavaAnything交流羣

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章