目錄java
最近在學習設計模式,在這篇博客中記錄下本身對裝飾者模式的理解。設計模式
在不改變原有對象的基礎之上,將功能附加到對象上。提供了比繼承更有彈性的替代方案(擴展原有對象功能)ide
能夠看出裝飾者模式是用來擴展對象的功能的。學習
接下來我舉一個比較接地氣的例子來講明下裝飾者模式的應用:賣手抓餅,根據配料的不一樣(加雞蛋或者火腿),價格也不一樣。咱們的目的是建立一個體系,能夠隨着配料的增長可以適配價格的計算而不用修改原來的代碼。測試
/** * 手抓餅父類 * @author asus * */ public class ShouZhuaBing { private String description="手抓餅"; public double price() { return 3; } public String getDescription() { return description; } }
抽象的裝飾者要繼承手抓餅類ui
/** * 手抓餅配料的父類 * @author asus * */ public abstract class PeiLiao extends ShouZhuaBing { //全部子類必須實現此方法 public abstract double price(); public abstract String getDescription(); }
具體的裝飾者中持有一個被裝飾對象的引用,經過實現抽象裝飾者的方法來加強被裝飾對象的功能,在這個例子中就是把配料本身的價格累加到手抓餅自己的價格上。this
/** * 雞蛋類(一個裝飾者,用來裝飾手抓餅) * @author asus * */ public class JiDan extends PeiLiao { private ShouZhuaBing shouZhuaBing; private double myCost=1; public JiDan(ShouZhuaBing shouZhuaBing) { this.shouZhuaBing=shouZhuaBing; } @Override public double price() { //累加被裝飾對象的價格和裝飾者的價格 return myCost+this.shouZhuaBing.price(); } @Override public String getDescription() { return this.shouZhuaBing.getDescription()+"+雞蛋"; } }
public class Client { public static void main(String[] args) { ShouZhuaBing shouZhuaBing1=new ShouZhuaBing(); //單純一個餅的價格 System.out.println(shouZhuaBing1.getDescription()+"-->"+shouZhuaBing1.price()+"元"); //加雞蛋的餅價格,(用雞蛋去裝飾原來的手抓餅) shouZhuaBing1=new JiDan(shouZhuaBing1); System.out.println(shouZhuaBing1.getDescription()+"-->"+shouZhuaBing1.price()+"元"); } }
上面的代碼中,先用手抓餅父類計算了一個價格,再經過雞蛋裝飾類計算了加上配料的價格。設計
/** * 火腿類(一個裝飾者,用來裝飾手抓餅) * @author asus * */ public class HuoTui extends PeiLiao { private ShouZhuaBing shouZhuaBing; private double myCost=2; public HuoTui(ShouZhuaBing shouZhuaBing) { this.shouZhuaBing=shouZhuaBing; } @Override public double price() { return myCost+this.shouZhuaBing.price(); } @Override public String getDescription() { return this.shouZhuaBing.getDescription()+"+火腿"; } }
這時若是想計算加上兩種配料的價格,能夠繼續使用裝飾者修飾手抓餅類的對象code
public static void main(String[] args) { ShouZhuaBing shouZhuaBing1=new ShouZhuaBing(); //單純一個餅的價格 System.out.println(shouZhuaBing1.getDescription()+"-->"+shouZhuaBing1.price()+"元"); //加雞蛋的餅價格,(用雞蛋去裝飾原來的手抓餅) shouZhuaBing1=new JiDan(shouZhuaBing1); System.out.println(shouZhuaBing1.getDescription()+"-->"+shouZhuaBing1.price()+"元"); //再加火腿後的價格,(繼續用火腿類裝飾) shouZhuaBing1=new HuoTui(shouZhuaBing1); System.out.println(shouZhuaBing1.getDescription()+"-->"+shouZhuaBing1.price()+"元"); }
經過以上的例子能夠發現,裝飾者模式中須要一個抽象裝飾者來約束具體裝飾者中的裝飾內容,而這個抽象裝飾者須要繼承被裝飾的對象。而後就能夠先建立一個被裝飾對象,再建立具體裝飾類的對象,把被裝飾對象做爲構造方法參數傳入。對象