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