1. 定義
Define the skeleton of an algorithm in an operation,deferring some steps to subclasses.TemplateMethod lets subclasses redefine certain steps of an algorithm without changing the algorithm'sstructure.
(定義一個操作中的算法的框架,而將一些步驟延遲到子類中。使得子類可以不改一個算法的結構即可重定義該算法的某些特定步驟。)
模板方法模式確實非常簡單,僅僅使用了Java的繼承機制,但它是一個應用非常廣泛的模式。
其中,AbstractClass叫做抽象模板,它的方法分爲兩類:
● 基本方法 基本方法也叫做基本操作,是由子類實現的方法,並且在模板方法被調用。
● 模板方法 可以有一個或幾個,一般是一個具體方法,也就是一個框架,實現對基本方法的調度,完成固定的邏輯。注意 爲了防止惡意的操作,一般模板方法都加上final關鍵字,不允許被覆寫。
抽象模板中的基本方法儘量設計爲protected類型,符合迪米特法則,不需要暴露的屬性或方法儘量不要設置爲protected類型。實現類若非必 要,儘量不要擴大父類中的訪問權限。
*在抽象類中某方法的返回值影響了模板方法的執行結果,該方法就叫做鉤子方法(Hook Method)
2.通用代碼
抽象模板類:
public abstract class AbstractClass { //基本方法 protected abstract void doSomething(); //基本方法 protected abstract void doAnything(); //模板方法 public void templateMethod(){ /* * 調用基本方法,完成相關的邏輯 */ this.doAnything(); this.doSomething(); } }
具體模板類:
public class ConcreteClass1 extends AbstractClass { //實現基本方法 protected void doAnything() { //業務邏輯處理 } protected void doSomething() { //業務邏輯處理 } } public class ConcreteClass2 extends AbstractClass { //實現基本方法 protected void doAnything() { //業務邏輯處理 } protected void doSomething() { //業務邏輯處理 } }
場景類:
public class Client { public static void main(String[] args) { AbstractClass class1 = new ConcreteClass1(); AbstractClass class2 = new ConcreteClass2(); //調用模板方法 class1.templateMethod(); class2.templateMethod(); } }
3.優點
● 封裝不變部分,擴展可變部分 把認爲是不變部分的算法封裝到父類實現,而可變部分的則可以通過繼承來繼續擴展。
● 提取公共部分代碼,便於維護
● 行爲由父類控制,子類實現 基本方法是由子類實現的,因此子類可以通過擴展的方式增加相應的功能,符合開閉原則。
4.缺點
按照我們的設計習慣,抽象類負責聲明最抽象、最一般的事物屬性和方法,實現類完成具體的事物屬性和方法。但是模板方法模式卻顛倒了,抽象類定義了部分抽象方法,由子類實現,子類執行的結果影響了父類的結果,也就是子類對父類產生了影響,這在複雜的項目中,會帶來代碼閱讀的難度,而且也會讓新手產生不適感。
5.使用場景
● 多個子類有公有的方法,並且邏輯基本相同時。
● 重要、複雜的算法,可以把核心算法設計爲模板方法,周邊的相關細節功能則由各個子類實現。
● 重構時,模板方法模式是一個經常使用的模式,把相同的代碼抽取到父類中,然後通過鉤子函數約束其行爲。