結構型模式————裝飾器模式(3.1)
- 2019 年 10 月 3 日
- 筆記
什麼是裝飾器模式?
【先吃三顆栗子:】
1.PC=主機+顯示器+鍵盤+滑鼠+滑鼠墊
主機是核心,而其他的組成部分都是裝飾。
2.手抓餅=餅+雞蛋+培根+黃瓜
餅是核心,雞蛋,培根是可選的,可以理解為裝飾。
3.咖啡=咖啡+牛奶+冰+方糖
咖啡是核心,牛奶等可選。
比喻雖然形象生動,但是與實際或多或少會產生偏差。
抽象的解釋:裝飾器模式的目的——核心部分和裝飾部分可以自由組合。
裝飾器模式的功能
對於軟體開發來說,聚焦於軟體的靈活性和可擴展性。
裝飾器模式要求:
- 裝飾可選
- 裝飾可擴展
- 核心部分可擴展
手抓餅中的裝飾器模式
實現餅加各種配料的價格計算。
思路:
1.定義抽象類手抓餅,其中包含獲取種類的抽象方法和獲取價格的抽象方法。
2.然後定義兩個分別為大份手抓餅和中份手抓餅來繼承這個抽象類,重寫兩個方法定義種類和價格。
3.定義具體的配料類繼承手抓餅抽象類,先定義構造器傳入已經創建的手抓餅種類,然後重寫種類和價格方法。
在網上看的一些部落格,是創建出一個抽象的配料類來繼承抽象產品類,然後用具體的配料類來實現抽象配料類,實現裝飾。
可是如果直接將抽象產品類的方法全部定義抽象方法,配料類直接繼承重寫,實現裝飾,功能上也是可以實現的,如下所示,Bacon類直接繼承HandPancake,然後重寫getName和getCost方法,實現裝飾。似乎也沒有問題:
但是設計模式畢竟是一種經驗總結,如果有已經看出端倪的小夥伴們在下方留言交流一下吧!
直接繼承HandPancake:
abstract class HandPancake { public abstract String getName(); public abstract int getCost(); } class HandPancake_Big extends HandPancake { @Override public String getName() { return "大份手抓餅"; } @Override public int getCost() { return 10; } } class HandPancake_Mid extends HandPancake { @Override public String getName() { return "中份手抓餅"; } @Override public int getCost() { return 8; } } class Bacon extends HandPancake { private HandPancake handPancake; Bacon(HandPancake handPancake) { this.handPancake=handPancake; } @Override public String getName() { return handPancake.getName()+"加培根"; } @Override public int getCost() { return handPancake.getCost()+1; } } class Cucumber extends HandPancake { private HandPancake handPancake; Cucumber(HandPancake handPancake) { this.handPancake=handPancake; } @Override public String getName() { return handPancake.getName()+"加黃瓜"; } @Override public int getCost() { return handPancake.getCost()+2; } } class Ham extends HandPancake { private HandPancake handPancake; Ham(HandPancake handPancake) { this.handPancake=handPancake; } @Override public String getName() { return handPancake.getName()+"加火腿"; } @Override public int getCost() { return handPancake.getCost()+1; } } public class APPlication { public static void main(String[] args) { HandPancake handPancake_big = new HandPancake_Big(); System.out.println("啥也不加"+handPancake_big.getName()+":"+handPancake_big.getCost()); handPancake_big = new Ham(handPancake_big); System.out.println(handPancake_big.getName()+":"+handPancake_big.getCost()); handPancake_big = new Cucumber(handPancake_big); System.out.println(handPancake_big.getName()+":"+handPancake_big.getCost()); handPancake_big = new Bacon(handPancake_big); System.out.println(handPancake_big.getName()+":"+handPancake_big.getCost()); System.out.println("=============================="); HandPancake handPancake_mid = new HandPancake_Mid(); System.out.println("啥也不加"+handPancake_mid.getName()+":"+handPancake_mid.getCost()); handPancake_mid = new Ham(handPancake_mid); System.out.println(handPancake_mid.getName()+":"+handPancake_mid.getCost()); handPancake_mid = new Cucumber(handPancake_mid); System.out.println(handPancake_mid.getName()+":"+handPancake_mid.getCost()); handPancake_mid = new Bacon(handPancake_mid); System.out.println(handPancake_mid.getName()+":"+handPancake_mid.getCost()); } }
官方做法:
abstract class HandPancake { String name; //1 public String getName() { return name; } public abstract int getCost(); } class HandPancake_Big extends HandPancake { HandPancake_Big() //2.通過構造器賦值 { name="大份手抓餅"; } @Override public int getCost() { return 10; } } class HandPancake_Mid extends HandPancake { HandPancake_Mid() //2.通過構造器賦值 { name="中份手抓餅"; } @Override public int getCost() { return 8; } } abstract class Condiments extends HandPancake //3.定義抽象介面 { public abstract String getName(); } class Bacon extends Condiments //4.繼承抽象介面 { private HandPancake handPancake; Bacon(HandPancake handPancake) { this.handPancake=handPancake; } @Override public String getName() { return handPancake.getName()+"加培根"; } @Override public int getCost() { return handPancake.getCost()+1; } } class Cucumber extends Condiments { private HandPancake handPancake; Cucumber(HandPancake handPancake) { this.handPancake=handPancake; } @Override public String getName() { return handPancake.getName()+"加黃瓜"; } @Override public int getCost() { return handPancake.getCost()+2; } } class Ham extends Condiments { private HandPancake handPancake; Ham(HandPancake handPancake) { this.handPancake=handPancake; } @Override public String getName() { return handPancake.getName()+"加火腿"; } @Override public int getCost() { return handPancake.getCost()+1; } } public class APPlication { public static void main(String[] args) { HandPancake handPancake_big = new HandPancake_Big(); System.out.println("啥也不加"+handPancake_big.getName()+":"+handPancake_big.getCost()); handPancake_big = new Ham(handPancake_big); System.out.println(handPancake_big.getName()+":"+handPancake_big.getCost()); handPancake_big = new Cucumber(handPancake_big); System.out.println(handPancake_big.getName()+":"+handPancake_big.getCost()); handPancake_big = new Bacon(handPancake_big); System.out.println(handPancake_big.getName()+":"+handPancake_big.getCost()); System.out.println("=============================="); HandPancake handPancake_mid = new HandPancake_Mid(); System.out.println("啥也不加"+handPancake_mid.getName()+":"+handPancake_mid.getCost()); handPancake_mid = new Ham(handPancake_mid); System.out.println(handPancake_mid.getName()+":"+handPancake_mid.getCost()); handPancake_mid = new Cucumber(handPancake_mid); System.out.println(handPancake_mid.getName()+":"+handPancake_mid.getCost()); handPancake_mid = new Bacon(handPancake_mid); System.out.println(handPancake_mid.getName()+":"+handPancake_mid.getCost()); } }
手抓餅的擴展性
- 創建手抓餅的種類
- 創建配料種類
官方的擴展:創建一個小份手抓餅繼承Hanpancake,然後創建配料繼承Condiments。
貼一下直接繼承HandPancake的情況:
class HandPancake_Smalll extends HandPancake
class Egg extends HandPancake
abstract class HandPancake { public abstract String getName(); public abstract int getCost(); } class HandPancake_Big extends HandPancake { @Override public String getName() { return "大份手抓餅"; } @Override public int getCost() { return 10; } } class HandPancake_Mid extends HandPancake { @Override public String getName() { return "中份手抓餅"; } @Override public int getCost() { return 8; } } class Bacon extends HandPancake { private HandPancake handPancake; Bacon(HandPancake handPancake) { this.handPancake=handPancake; } @Override public String getName() { return handPancake.getName()+"加培根"; } @Override public int getCost() { return handPancake.getCost()+1; } } class Cucumber extends HandPancake { private HandPancake handPancake; Cucumber(HandPancake handPancake) { this.handPancake=handPancake; } @Override public String getName() { return handPancake.getName()+"加黃瓜"; } @Override public int getCost() { return handPancake.getCost()+2; } } class Ham extends HandPancake { private HandPancake handPancake; Ham(HandPancake handPancake) { this.handPancake=handPancake; } @Override public String getName() { return handPancake.getName()+"加火腿"; } @Override public int getCost() { return handPancake.getCost()+1; } } //======================== class HandPancake_Smalll extends HandPancake { @Override public String getName() { return "小份手抓餅"; } @Override public int getCost() { return 5; } } class Egg extends HandPancake { private HandPancake handPancake; Egg(HandPancake handPancake) { this.handPancake=handPancake; } @Override public String getName() { return handPancake.getName()+"加雞蛋"; } @Override public int getCost() { return handPancake.getCost()+1; } } public class APPlication { public static void main(String[] args) { HandPancake handPancake_big = new HandPancake_Big(); System.out.println("啥也不加"+handPancake_big.getName()+":"+handPancake_big.getCost()); handPancake_big = new Ham(handPancake_big); System.out.println(handPancake_big.getName()+":"+handPancake_big.getCost()); handPancake_big = new Cucumber(handPancake_big); System.out.println(handPancake_big.getName()+":"+handPancake_big.getCost()); handPancake_big = new Bacon(handPancake_big); System.out.println(handPancake_big.getName()+":"+handPancake_big.getCost()); System.out.println("=============================="); HandPancake handPancake_mid = new HandPancake_Mid(); System.out.println("啥也不加"+handPancake_mid.getName()+":"+handPancake_mid.getCost()); handPancake_mid = new Ham(handPancake_mid); System.out.println(handPancake_mid.getName()+":"+handPancake_mid.getCost()); handPancake_mid = new Cucumber(handPancake_mid); System.out.println(handPancake_mid.getName()+":"+handPancake_mid.getCost()); handPancake_mid = new Bacon(handPancake_mid); System.out.println(handPancake_mid.getName()+":"+handPancake_mid.getCost()); System.out.println("擴展性測試:"); HandPancake handPancake_small = new HandPancake_Smalll(); System.out.println("啥也不加"+handPancake_small.getName()+":"+handPancake_small.getCost()); handPancake_small = new Egg(handPancake_small); System.out.println(handPancake_small.getName()+":"+handPancake_small.getCost()); } }
運行結果: