結構型模式————裝飾器模式(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());          }  }

1565696683438

官方做法:

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());          }  }

1565696715504

手抓餅的擴展性

  • 創建手抓餅的種類
  • 創建配料種類

官方的擴展:創建一個小份手抓餅繼承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());                  }  }

運行結果:

1565696654138