模板方法是結構最簡單的行為型設計模式,在抽象類中定義了一個稱為模板方法的方法,在這個方法中定義其他基本方法的執行步驟,而基本方法的實現可以放在抽象類,也可以放在其子類 模式動機 現實生活中很多事情的完成過程都包含幾個基本步驟,例如請客吃飯,無論吃什麼,一般都包含點單、吃東西、買單幾個步驟,到底吃什麼 ...
模板方法是結構最簡單的行為型設計模式,在抽象類中定義了一個稱為模板方法的方法,在這個方法中定義其他基本方法的執行步驟,而基本方法的實現可以放在抽象類,也可以放在其子類
模式動機
現實生活中很多事情的完成過程都包含幾個基本步驟,例如請客吃飯,無論吃什麼,一般都包含點單、吃東西、買單幾個步驟,到底吃什麼則具體情況具體分析,在實際環境中由用戶動態決定。
既然這幾個步驟的次序是固定的,於是我們創建一個新的方法叫“請客”,在其中調用了點單、吃東西和買單,同時指定它們的執行次序,我們稱這個“請客”為模板方法,“點單”、“吃東西”、“買單”都是“請客”過程中的一個步驟,它們稱為基本方法。其中“吃東西”可以有多種吃法,如吃飯、吃麵條、吃燒烤,因此需要提供不同的“吃東西”方法的實現。
假設用代碼實現上述方法,我們可以把相同代碼放在父類,如“點單”和“買單”,而將不同方法實現放在不同的子類,如“吃東西”,這樣一來提高了代碼的復用性,還可以利用面向對象的多態性,這就是模板方法模式的模式動機。
模式定義
定義一個操作中演算法的骨架,而將一些步驟延遲到子類中,模板方法使得子類可以不改變一個演算法的結構即可重新定義該演算法的某些特定步驟
Define the skeleton of an algorithm in an operation, deferring some steps to subclasses. Template Method lets subclasses redefine certain steps of an algorithm without changing the algorithm’s structure.
模式分析
模板方法模式是基於繼承的代碼復用基本技術,先在抽象類的模板方法中指定執行步驟,將相同步驟對應的方法在抽象父類中實現,而不同的步驟只在抽象父類中進行聲明。由於面向對象的多態性,子類中定義的方法將覆蓋父類中定義的方法,因此程式運行時,具體子類的基本方法將覆蓋父類中定義的基本方法,實現特定的演算法。
不過,雖然說子類覆蓋了父類的方法實現業務邏輯,但實際上是由父類來控制整個過程,即子類不需要調用父類,而通過父類來調用子類。
由此得模式結構類圖如下:
抽象類(AbstractClass)中定義一系列基本操作(primitiveOperation),這些基本操作可以是具體的,也可以是抽象的,每一個基本操作對應演算法的一個步驟,在其子類中可以重定義並實現一個演算法的各個步驟。同時在抽象類中實現了一個模板方法(templateMethod),用於定義一個演算法的骨架,調用基本操作。
具體子類(ConcreteClass)用於實現在父類中定義的抽象基本操作以完成子類特定演算法的步驟,也可以覆蓋在父類中實現的具體基本操作。
基本方法是實現各個步驟的方法,是模板方法的組成部分,基本方法又可以分為三種:
-
抽象方法
一個抽象方法由抽象類聲明,由其具體子類實現
-
具體方法
一個具體方法由一個抽象類或具體類聲明並實現,其子類可以進行覆蓋
-
鉤子方法
一個鉤子方法由一個抽象類或具體類聲明並實現,而其子類可能會加以擴展。通常在父類中給出的實現是一個空實現,作為該方法的預設實現,當然也可以提高一個非空的預設實現。
鉤子方法有兩類,一類是可以控制具體步驟的執行,比如說我們希望在不同條件下執行模板方法中的不同步驟,就可以定義一個返回類型為布爾值的鉤子方法,用於進行條件判斷,如果條件滿足則執行某一步驟,否則某一步驟不執行
public void template() { open(); display(); if(isPrint()) { print(); } } public boolean isPrint(){ return true; }
如果不希望方法執行,可以在其子類在覆蓋鉤子方法,修改返回值即可。
還有一類鉤子方法是實現體為空的具體方法,子類根據需要覆蓋或繼承它們,與抽象方法相比,鉤子方法的好處在於如果沒有覆蓋父類中定義的抽象方法,編譯仍可以通過。
模式優缺點
模板方法模式的優點:
- 可以在一個類中形式化地定義演算法,而由它的子類實現細節的處理
- 模板方法模式是一種代碼復用的基本技術,在類庫設計中尤其重要,它提取類庫中的公共行為,將公共行為放在父類,通過子類來實現不同的行為
- 通過一個父類調用其子類的操作,通過對子類的擴展增加新的行為,符合開閉原則
模板方法模式的缺點:
- 每個不同的實現都需要定義一個子類,將會導致類的個數增加