裝飾者模式屬於結構型模式,它能夠動態的將新功能附加到對象上,同時又不改變其結構。在對象功能擴展方面,它比繼承更有彈性,裝飾者模式也體現了開閉原則(OCP)。java
裝飾者和被裝飾者有相同的超類型,由於裝飾者和被裝飾者必須是同樣的類型,利用繼承是爲了達到類型的匹配,而不是利用繼承獲取行爲git
在咖啡店客人想點一杯加兩份糖一份牛奶的摩卡咖啡,各個商品的價格以下,咱們須要根據用戶點的咖啡、加的配料,動態的計算價格github
商品 | 價格 |
---|---|
拿鐵咖啡(LatteCoffee) | 4.5 |
摩卡咖啡(MochaCoffe) | 5.5 |
糖(Sugar) | 1.0 |
牛奶(Milk) | 2.0 |
「實體類」 Coffeeide
public abstract class Coffee{ public String des = "咖啡"; //描述 private float price = 0.0f; //價格 protected abstract float cost(); //計算費用 //省略getter setter方法 }
「被裝飾者」LatteCoffee測試
public class LatteCoffee extends Coffee{ public LatteCoffee() { setDes("拿鐵咖啡"); setPrice(4.5f); } @Override protected float cost() { return getPrice(); } }
「被裝飾者」MochaCoffeethis
public class MochaCoffee extends Coffee { public MochaCoffee() { setDes("摩卡咖啡"); setPrice(5.5f); } @Override protected float cost() { return getPrice(); } }
「抽象裝飾者」Decorator設計
public class Decorator extends Coffee { private Coffee coffee; public Decorator(Coffee drink) { this.coffee = drink; } @Override protected float cost() { return getPrice() + coffee.cost(); } @Override public String getDes() { return coffee.getDes() + "加" + super.getDes(); } }
「具體裝飾者」SugarDecoratorcode
public class SugarDecorator extends Decorator{ public SugarDecorator(Coffee coffee) { super(coffee); setDes("糖"); setPrice(1.0f); } }
「具體裝飾者」MilkDecorator對象
public class MilkDecorator extends Decorator{ public MilkDecorator(Coffee coffee) { super(coffee); setDes("牛奶"); setPrice(2.0f); } }
「測試類」Client繼承
public class Client { /** * 點一杯 加兩份糖一份牛奶的摩卡咖啡 */ @Test public void test01() { Coffee order = new MochaCoffee(); System.out.println(order.getDes() + ",價格:" + order.cost()); //加兩份糖 order = new SugarDecorator(new SugarDecorator(order)); System.out.println(order.getDes() + ",價格:" + order.cost()); //加一份牛奶 order = new MilkDecorator(order); System.out.println(order.getDes() + ",價格:" + order.cost()); } }
「結果」result
摩卡咖啡,價格:5.5 摩卡咖啡加糖加糖,價格:7.5 摩卡咖啡加糖加糖加牛奶,價格:9.5
在上圖所示的關係中
具體使用以下:
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("G:\\a.txt"));
一、利用繼承設計子類,只能在編譯時靜態決定,而且全部子類都會繼承相同的行爲;利用組合擴展對象,就能夠在運行時動態的進行擴展。
二、裝飾者和被裝飾者對象有相同的超類型,因此在任何須要原始對象(被裝飾者)的場合,均可以用裝飾過的對象代替原始對象。
三、能夠用一個或多個裝飾者包裝一個對象(被裝飾者)。
四、裝飾者能夠在所委託的裝飾者行爲以前或以後加上本身的行爲,以達到特定的目的。
五、被裝飾者能夠在任什麼時候候被裝飾,因此能夠在運行時動態地、不限量地用你喜歡的裝飾者來裝飾對象。
p.s. 全部代碼和筆記都可在 個人GitHub 中獲取,若是對您有幫助的話,能夠點個 star 支持一下 🙈