1、 裝飾者模式,動態地將責任附加到物件上。若要擴充套件功能,裝飾者提供了比繼承更加有彈性的替代方案。
2、組合和繼承的區別
繼承。繼承是給一個類新增行為的比較有效的途徑。透過使用繼承,可以使得子類在擁有自身方法的同時,還可以擁有父類的方法。但是使用繼承是靜態的,在編譯的時候就已經決定了子類的行為,我們不便於控制增加行為的方式和時機。
組合。組合即將一個物件嵌入到另一個物件中,由另一個物件來決定是否引用該物件來擴充套件自己的行為。這是一種動態的方式,我們可以在應用程式中動態的控制。
與繼承相比,組合關係的優勢就在於不會破壞類的封裝性,且具有較好的松耦合性,可以使系統更加容易維護。但是它的缺點就在於要建立比繼承更多的物件。
3、裝飾者模式的優缺點
優點
1、裝飾者模式可以提供比繼承更多的靈活性
2、可以透過一種動態的方式來擴充套件一個物件的功能,在執行時選擇不同的裝飾器,從而實現不同的行為。
3、透過使用不同的具體裝飾類以及這些裝飾類的排列組合,可以創造出很多不同行為的組合。可以使用多個具體裝飾類來裝飾同一物件,得到功能更為強大的物件。
4、具體構件類與具體裝飾類可以獨立變化,使用者可以根據需要增加新的具體構件類和具體裝飾類,在使用時再對其進行組合,原有程式碼無須改變,符合“開閉原則”。
缺點
1、會產生很多的小物件,增加了系統的複雜性
2、這種比繼承更加靈活機動的特性,也同時意味著裝飾模式比繼承更加易於出錯,排錯也很困難,對於多次裝飾的物件,除錯時尋找錯誤可能需要逐級排查,較為煩瑣。
4、裝飾者的使用場景
1、在不影響其他物件的情況下,以動態、透明的方式給單個物件新增職責。
2、需要動態地給一個物件增加功能,這些功能也可以動態地被撤銷。 當不能採用繼承的方式對系統進行擴充或者採用繼承不利於系統擴充套件和維護時。
以上內容來自網路
5、UML圖(Astah/jude)下載地址:http://pan.baidu.com/s/1eQiVePc
6、示例:
裝飾者基類
package com.xinye.test.decoration; /** * 食物基類 * @author xinye * */ public abstract class Food { protected String desc; public abstract String getDesc(); }
雞肉
package com.xinye.test.decoration; /** * 雞肉 * @author xinye * */ public class Chicken extends Food { public Chicken(){ desc = "雞肉"; } @Override public String getDesc() { return desc; } }
鴨肉
package com.xinye.test.decoration; /** * 鴨肉 * @author xinye * */ public class Duck extends Food { public Duck(){ desc = "鴨肉"; } @Override public String getDesc() { return desc; } }
裝飾者基類
package com.xinye.test.decoration; /** * * @author xinye * */ public abstract class FoodDecoration extends Food { @Override public abstract String getDesc(); }
蒸-裝飾者
package com.xinye.test.decoration; /** * 蒸食物 * @author xinye * */ public class SteamedFood extends FoodDecoration { private Food food; public SteamedFood(Food f){ this.food = f; } @Override public String getDesc() { return getDecoration() + food.getDesc(); } private String getDecoration(){ return "蒸"; } }
烤-裝飾者
package com.xinye.test.decoration; /** * 烤食物 * @author xinye * */ public class RoastFood extends FoodDecoration { private Food food; public RoastFood(Food f){ this.food = f; } @Override public String getDesc() { return getDecoration() + food.getDesc(); } private String getDecoration(){ return "烤"; } }
客戶端
package com.xinye.test.decoration; /** * 客戶端 * @author xinye * */ public class Client { public static void main(String[] args) { // 測試單純的食物 Food f1 = new Chicken(); System.out.println(f1.getDesc()); System.out.println("----------------------"); // 測試單重修飾的食物 RoastFood rf = new RoastFood(f1); System.out.println(rf.getDesc()); System.out.println("----------------------"); // 測試多重修飾的食物 SteamedFood sf = new SteamedFood(rf); System.out.println(sf.getDesc()); } }
執行結果:
雞肉 ---------------------- 烤雞肉 ---------------------- 蒸烤雞肉