初识设计模式(装饰者模式)
?前言:總結這兩天學到的裝飾者模式,并用java小小的實現一下。書中有寫到:給愛用繼承的人一個全新的設計眼界。(ps,本文最后有個小問題待解決)
什么是裝飾者模式(Decorator Pattern)?
定義:動態地將責任附加到對象上。若要擴展功能,裝飾者提供了比繼承更有彈性的替代方案。
使用的設計原則:開放-關閉原則,類應該對擴展開放,對修改關閉。
代表:Java IO 流
類圖:
?
裝飾者模式的優缺點?
優點:
缺點:
什么情況下使用裝飾者模式?
舉例說明
場景:現在需要炒一盤菜,可以給這盤菜加多種作料,這盤菜也可以有不同作料的組合。
實現:(如果只有一盤菜存在,不會再有第二盤菜的情況,也可以不創建抽象組件,直接創建具體組件,抽象的裝飾類繼承具體組件。)
- 先創建抽象組件 1 /** 2 * 抽象組件 一盤菜 3 */ 4 abstract class Dish{ 5 protected String name; 6 7 public String getName(){ 8 return this.name; 9 } 10 }
- 然后創建具體組件 1 /** 2 * 具體組件 3 */ 4 class MeatDish extends Dish{ 5 public MeatDish(){ 6 super.name = "meatDish"; 7 } 8 }
- 然后創建抽象裝飾類 1 /** 2 * 抽象裝飾類 作料 3 */ 4 abstract class Seasoning extends Dish{ 5 @Override 6 public abstract String getName(); 7 }
- 然后創建抽象具體裝飾類 1 /** 2 * 具體裝飾類 鹽 3 */ 4 class Salt extends Seasoning{ 5 private Dish dish; 6 public Salt(Dish dish){ 7 this.dish = dish; 8 } 9 @Override 10 public String getName() { 11 return this.dish.getName() + " ,Salt"; 12 } 13 } 14 15 /** 16 * 具體裝飾類,雞精 17 */ 18 class ChickenPowder extends Seasoning{ 19 private Dish dish; 20 public ChickenPowder(Dish dish){ 21 this.dish = dish; 22 } 23 @Override 24 public String getName() { 25 return this.dish.getName() + " ,ChickenPowder"; 26 } 27 }
- 然后測試 1 public static void main(String[] args){ 2 Dish dish = new MeatDish(); 3 System.out.println(dish.getName()); 4 5 dish = new Salt(dish); 6 dish = new ChickenPowder(dish); 7 System.out.println(dish.getName()); 8 }
- 最后輸出結果
總結:
提問:
問:不是說這個讓愛用繼承的人改變眼界嗎?怎么類圖還是使用的繼承?
答:?這么做的重點在于,裝飾者和被裝飾者必須是一樣的類型,也就是有共同的超類,這是相當關鍵的地方。在這里,是利用繼承達到“類型匹配”,而不是利用繼承獲得“行為”。
問:那么行為從哪里來?
答:當我們將裝飾者與組件組合時,就是在加入新的行為。所得到的新行為,并不是繼承自超類,而是由組合對象得來的。如果這里依賴繼承,那么類的行為只能只能在編譯時靜態決定。換句話說,行為如果不是來自超類,就是子類覆蓋后的版本。反之,利用組合,可以把裝飾者混合著用,而且是在運行時。這樣,就可以在任何時候實現新的裝飾者增加新的行為,如果依賴繼承,每當需要新行為時,還得修改現有的代碼。
問:為什么Componet要設計為一個抽象類,而不是一個接口?
答:通常裝飾者模式是采用抽象類。(有大神知道的嗎?還請不吝賜教)
?
參考書籍:《Head First 設計模式》《大話設計模式》
轉載于:https://www.cnblogs.com/yuxiaole/p/9220672.html
總結
以上是生活随笔為你收集整理的初识设计模式(装饰者模式)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Runtime消息动态解析与转发流程
- 下一篇: 流畅的python mobi 百度云_流