JAVA 設計模式 模板方法模式


定義


模板方法模式 (Template Method)
定義了一個操作中的 算法的骨架,而將 部分步驟的實現在子類中完成。
模板方法模式使得子類可以不改變一個算法的結構即可重定義該算法的某些特定步驟。

模板方法模式是所有模式中最為常見的幾個模式之一,是基於繼承代碼復用的基本技術。,沒有關聯關系。

因此,在模板方法模式的類結構圖中,只有繼承關系

模板方法模式需要開發抽象類和具體子類的設計師之間的協作。一個設計師負責給出一個算法的輪廓和骨架,另一些設計師則負責給出這個算法的各個邏輯步驟。

代表這些具體邏輯步驟的方法稱做 基本方法(primitive method);而將這些基本方法匯總起來的方法叫做 模板方法(template method),這個設計模式的名字就是從此而來。

 


結構


圖-模板方法模式結構圖

AbstractClass : 抽象類,定義並實現一個模板方法。這個模板方法定義了算法的骨架,而邏輯的組成步驟在相應的抽象操作中,推遲到子類去實現。頂級邏輯也有可能調用一些具體方法。

abstract  class AbstractClass {
     public  abstract  void PrimitiveOperation1();
     public  abstract  void PrimitiveOperation2();
    
     public  void TemplateMethod() {
        PrimitiveOperation1();
        PrimitiveOperation2();
    }
}
ConcreteClass : 實現實現父類所定義的一個或多個抽象方法。
class ConcreteClassA  extends AbstractClass {
    @Override
     public  void PrimitiveOperation1() {
        System.out.println("具體A類方法1");
    }

    @Override
     public  void PrimitiveOperation2() {
        System.out.println("具體A類方法2");
    }
}

class ConcreteClassB  extends AbstractClass {
    @Override
     public  void PrimitiveOperation1() {
        System.out.println("具體B類方法1");
    }

    @Override
     public  void PrimitiveOperation2() {
        System.out.println("具體B類方法2");
    }    
}
測試代碼
public  class TemplateMethodPattern {
     public  static  void main(String[] args) {
        AbstractClass objA =  new ConcreteClassA();
        AbstractClass objB =  new ConcreteClassB();    
        objA.TemplateMethod();
        objB.TemplateMethod();
    }
}



要點


模板方法模式中的三類角色
1、具體方法(Concrete Method)

2、抽象方法(Abstract Method)

3、鈎子方法(Hook Method)

三類角色的關聯

在模板方法模式中,首先父類會定義一個算法的框架,即實現算法所必須的所有方法。

其中,具有共性的代碼放在父類的具體方法中。

各個子類特殊性的代碼放在子類的具體方法中。但是父類中需要有對應抽象方法聲明。

鈎子方法可以讓子類決定是否對算法的不同點進行掛鈎。

總結

使用模板方法模式可以將代碼的公共行為提取,以達到復用的目的。

而對於特殊化的行為在子類中實現。父類的模板方法可以控制子類中的具體實現。

子類無需了解整體算法框架,只需實現自己的業務邏輯即可。

 

 

實例


模板方法模式應用場景十分廣泛。

《Head First》的模板方法模式章節里列舉了一個十分具有代表性的例子。 

現實生活中,茶和咖啡是隨處可見的飲料。沖泡一杯茶或沖泡一杯咖啡的過程是怎樣的?

我們來整理一下流程。

泡茶:
燒開水 ==> 沖泡茶葉 ==> 倒入杯中 ==> 添加檸檬
泡咖啡:
燒開水 ==> 沖泡咖啡 ==> 倒入杯中 ==> 添加糖和牛奶

由以上處理步驟不難發現,准備這兩種飲料的處理過程非常相似。我們可以使用模板類方法去限定制作飲料的算法框架。

其中相同的具有共性的步驟(如燒開水、倒入杯中),直接在抽象類中給出具體實現。

而對於有差異性的步驟,則在各自的具體類中給出實現。

抽象類
abstract  class Beverage {

     //  模板方法,決定了算法骨架。相當於TemplateMethod()方法
     public  void prepareBeverage() {
        boilWater();
        brew();
        pourInCup();
         if (customWantsCondiments())
        {
            addCondiments();
        }
    }
    
     //  共性操作,直接在抽象類中定義
     public  void boilWater() {
        System.out.println("燒開水");
    }
    
     //  共性操作,直接在抽象類中定義
     public  void pourInCup() {
        System.out.println("倒入杯中");
    }
    
     //  鈎子方法,決定某些算法步驟是否掛鈎在算法中
     public  boolean customWantsCondiments() {
         return  true;
    }
    
     //  特殊操作,在子類中具體實現
     public  abstract  void brew();
    
     //  特殊操作,在子類中具體實現
     public  abstract  void addCondiments();
    
}
具體類
class Tea  extends Beverage {

    @Override
     public  void brew() {
        System.out.println("沖泡茶葉");
    }

    @Override
     public  void addCondiments() {
        System.out.println("添加檸檬");
    }
    
}

class Coffee  extends Beverage {

    @Override
     public  void brew() {
        System.out.println("沖泡咖啡豆");
    }

    @Override
     public  void addCondiments() {
        System.out.println("添加糖和牛奶");
    }
    
}
測試代碼
public  static  void main(String[] args) {
        
    System.out.println("============= 准備茶 =============");
    Beverage tea =  new Tea();
    tea.prepareBeverage();
    
    System.out.println("============= 准備咖啡 =============");
    Beverage coffee =  new Coffee();
    coffee.prepareBeverage();
    
}
運行結果
============= 准備茶 =============
燒開水
沖泡茶葉
倒入杯中
添加檸檬
============= 准備咖啡 =============
燒開水
沖泡咖啡豆
倒入杯中
添加糖和牛奶



 

推薦

本文屬於 JAVA設計模式系列

 

 

參考資料

《大話設計模式》

《HeadFirst設計模式》

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM