1. 程式人生 > >“Head First 設計模式“ :模板方法模式

“Head First 設計模式“ :模板方法模式

設計模式 模板方法模式 模板方法

模板方法模式

定義:模板方法模式在一個方法中定義一個算法的骨架,而將一些步驟延遲到子類中。模板方法使得子類可以在不改變算法結構的情況下,重新定義算法中的某些步驟。模板方法就是一個固定步驟的“算法”骨架方法。這個算法的可變部分通過繼承,在子類中重載實現。這樣就可以在算法骨架不變的情況下,算法細節步驟根據不同的需求進行適應的改變,類圖如下:
技術分享圖片


優點
● 模板方法模式在定義了一組算法,將具體的實現交由子類負責。
● 模板方法模式是一種代碼復用的基本技術。
● 模板方法模式導致一種反向的控制結構,通過一個父類調用其子類的操作,通過對子類的擴展增加新的行為,符合“開閉原則”。


缺點
● 每一個不同的實現都需要一個子類來實現,導致類的個數增加,是的系統更加龐大。


使用場景
● 一次性實現一個算法的不變的部分,並將可變的行為留給子類來實現。
● 各子類中公共的行為應被提取出來並集中到一個公共父類中以避免代碼重復。
● 控制子類的擴展。


案例1:泡茶,泡咖啡有好多共同步驟,如下:
● 煮沸水
● 加入茶葉沖泡(咖啡粉)
● 根據需求加入調料(如蜂蜜、檸檬,糖)
● 將泡好的茶水倒入杯子
泡茶代碼如下(咖啡也類似,所以省略了哦):

public class Tea {
   // 執行步驟
   void prepareRecipe() {
      boilWater();
      steepTeaBag();
      pourInCup();
      addLemon();
   }
   public void boilWater() { System.out.println("Boiling water");}
   public void steepTeaBag() {System.out.println("Steeping the tea"); }
   public void addLemon() { System.out.println("Adding Lemon"); }
   public void pourInCup() { System.out.println("Pouring into cup");}
}

我們不難發現這兩個類中代碼重復了很多,步驟一樣,我們可以封裝起來,我們用模板方法模式來修改,如下:
模板方法代碼:

public abstract class CaffeineBeverage {
   final void prepareRecipe() {
      boilWater();
      brew();
      pourInCup();
      addCondiments();
   }
   abstract void brew();
   abstract void addCondiments();
   void boilWater() {
      System.out.println("Boiling water");
   }
   void pourInCup() {
      System.out.println("Pouring into cup");
   }
}

泡茶代碼:

public class Tea extends CaffeineBeverage {
    public void brew() {
        System.out.println("Steeping the tea");
    }
    public void addCondiments() {
        System.out.println("Adding Lemon");
    }
}

總結:子類可以靈活實現每個步驟的具體邏輯,執行步驟用抽象類裏的prepareRecipe()方法決定。


案例2:鉤子的使用,鉤子就是一個boolean狀態,控制prepareRecipe()裏是否需要執行某個步驟代碼(子類自行修改),如下:

public abstract class CaffeineBeverageWithHook {
   void prepareRecipe() {
      boilWater();
      brew();
      pourInCup();
      if (customerWantsCondiments()) {
         addCondiments();
      }
   }
   abstract void brew();
   abstract void addCondiments();
   void boilWater() { System.out.println("Boiling water");}
   void pourInCup() { System.out.println("Pouring into cup"); }
  // 鉤子方法
    boolean customerWantsCondiments() {
      return true;
   }
}

Java中的模板方法模式:
● Applet
● Swing裏的JFrame
● java.io.InputStream, java.io.OutputStream, java.io.Reader 以及 java.io.Writer 中所有非抽象方法。
● java.util.AbstractList, java.util.AbstractSet 以及 java.util.AbstractMap中所有非抽象方法。


設計原則:好菜鳥原則,不要找我們,我們會找你的。

“Head First 設計模式“ :模板方法模式