模式定義
定義一個操作中算法的骨架,而將一些步驟延遲到子類中,模板方法使得子類可以不改變一個算法的結構即可重定義該算法的某些特定步驟
- 類行為型模式
模式結構
- AbstractClass:抽象類
- ConcreteClass:具體子類
只有類之間的繼承關系,沒有對象關聯關系
- 體現繼承優勢的模式之一
好萊塢原則(Hollywood Principle)
- Don‘t call us, we’ll call you.
- 子類不顯式調用父類的方法,而是通過override父類的方法來實現某些具體的業務邏輯,父類控制對子類的調用
通過在子類中實現的鉤子方法override父類鉤子方法,對父類方法的執行進行約束,實現子類對父類行為的反向控制
- 基本方法(Primitive Method):實現具體邏輯步驟的方法
- 抽象方法(Abstract Method)
- 具體方法(Concrete Method)
- 鉤子方法(Hook Method):“掛鉤”方法和空方法
......public void template() {open();display();if(isPrint()) {print();} }// Hook Method public boolean isPrint() {return true; }......
- 鉤子方法的引入使得子類可以控制父類的行為
- 最簡單的鉤子方法就是空方法,也可以在鉤子方法中定義一個默認的實現,如果子類不覆蓋鉤子方法,則執行父類的默認實現代碼
- 比較復雜一點的鉤子方法可以對其他方法進行約束
- 這種鉤子方法通常返回一個boolean類型,即返回true或false,用來判斷是否執行某一個基本方法
- 模板方法(Template Method):匯總基本方法的方法
抽象類代碼
public abstract class AbstractClass {// 模板方法public void templateMethod() {primitiveOperation1();primitiveOperation2();primitiveOperation3();}// 基本方法—具體方法public void primitiveOperation1() {// do something}// 基本方法—抽象方法public abstract void primitiveOperation2();// 基本方法—鉤子方法public void primitiveOperation3() {// do something}}
具體子類代碼
public class ConcreteClass extends AbstractClass {public void primitiveOperation2() {// do something}public void primitiveOperation3() {// do something}}
實例
實例一:銀行業務辦理流程
在銀行辦理業務時,一般都包含幾個基本步驟,首先需要取號排隊,然后辦理具體業務,最后需要對銀行工作人員進行評分。無論具體業務是取款、存款還是轉賬,其基本流程都一樣。用模板方法模式模擬銀行業務辦理流程。
實例二:數據庫操作模板
對數據庫的操作一般包括連接、打開、使用、關閉等步驟,在數據庫操作模板類中我們定義了connDB()、openDB()、useDB()、closeDB()四個方法分別對應這四個步驟。對于不同類型的數據庫(如SQL Server和Oracle),其操作步驟都一致,只是連接數據庫connDB()方法有所區別,使用模板方法模式對其進行設計。
模式分析
- 優點
- 模板方法模式在一個類中抽象地定義算法,而由它的子類實現
細節的處理 - 模板方法模式是一種代碼復用的基本技術
- 模板方法模式導致一種反向的控制結構(Hook Method),通過一個父類調用其
子類的操作,通過對子類的擴展增加新的行為- 符合開閉原則
- 模板方法模式在一個類中抽象地定義算法,而由它的子類實現
- 缺點
- 每個不同的實現都需要定義一個子類,這會導致類的個數增加,系統更加龐大,設計也更加抽象
- 但是更加符合“單一職責原則”,使得類的內聚性得以提高
- 每個不同的實現都需要定義一個子類,這會導致類的個數增加,系統更加龐大,設計也更加抽象
適用環境
- 一次性實現一個算法的不變的部分,并將可變的行為留給子類來實現
- 各子類中公共的行為被提取出來并集中到一個公共父類中以避免代碼重復
- 對一些復雜的算法進行分割,將其算法中固定不變的部分設計為模板方法和父類具體方法,而一些可以改變的細節由其子類來實現
- 控制子類的擴展