更新時間:2021-08-24 來源:黑馬程序員 瀏覽量:
在面向對象程序設計過程中,程序員常常會遇到這種情況:設計一個系統時知道了算法所需的關鍵步驟,而且確定了這些步驟的執行順序,但某些步驟的具體實現還未知,或者說某些步驟的實現與具體的環境相關。
例如,去銀行辦理業務一般要經過以下4個流程:取號、排隊、辦理具體業務、對銀行工作人員進行評分等,其中取號、排隊和對銀行工作人員進行評分的業務對每個客戶是一樣的,可以在父類中實現,但是辦理具體業務卻因人而異,它可能是存款、取款或者轉賬等,可以延遲到子類中實現。
模板方法(Template Method)模式包含以下主要角色:
抽象類(Abstract Class):負責給出一個算法的輪廓和骨架。它由一個模板方法和若干個基本方法構成。
模板方法:定義了算法的骨架,按某種順序調用其包含的基本方法。
基本方法:是實現算法各個步驟的方法,是模板方法的組成部分。基本方法又可以分為三種:
抽象方法(Abstract Method) :一個抽象方法由抽象類聲明、由其具體子類實現。
具體方法(Concrete Method) :一個具體方法由一個抽象類或具體類聲明并實現,其子類可以進行覆蓋也可以直接繼承。
鉤子方法(Hook Method) :在抽象類中已經實現,包括用于判斷的邏輯方法和需要子類重寫的空方法兩種。
一般鉤子方法是用于判斷的邏輯方法,這類方法名一般為isXxx,返回值類型為boolean類型。
具體子類(Concrete Class):實現抽象類中所定義的抽象方法和鉤子方法,它們是一個頂級邏輯的組成步驟。
【例】炒菜
炒菜的步驟是固定的,分為倒油、熱油、倒蔬菜、倒調料品、翻炒等步驟。現通過模板方法模式來用代碼模擬。類圖如下:
代碼如下:
public abstract class AbstractClass { public final void cookProcess() { //第一步:倒油 this.pourOil(); //第二步:熱油 this.heatOil(); //第三步:倒蔬菜 this.pourVegetable(); //第四步:倒調味料 this.pourSauce(); //第五步:翻炒 this.fry(); } public void pourOil() { System.out.println("倒油"); } //第二步:熱油是一樣的,所以直接實現 public void heatOil() { System.out.println("熱油"); } //第三步:倒蔬菜是不一樣的(一個下包菜,一個是下菜心) public abstract void pourVegetable(); //第四步:倒調味料是不一樣 public abstract void pourSauce(); //第五步:翻炒是一樣的,所以直接實現 public void fry(){ System.out.println("炒啊炒啊炒到熟啊"); } } public class ConcreteClass_BaoCai extends AbstractClass { @Override public void pourVegetable() { System.out.println("下鍋的蔬菜是包菜"); } @Override public void pourSauce() { System.out.println("下鍋的醬料是辣椒"); } } public class ConcreteClass_CaiXin extends AbstractClass { @Override public void pourVegetable() { System.out.println("下鍋的蔬菜是菜心"); } @Override public void pourSauce() { System.out.println("下鍋的醬料是蒜蓉"); } } public class Client { public static void main(String[] args) { //炒手撕包菜 ConcreteClass_BaoCai baoCai = new ConcreteClass_BaoCai(); baoCai.cookProcess(); //炒蒜蓉菜心 ConcreteClass_CaiXin caiXin = new ConcreteClass_CaiXin(); caiXin.cookProcess(); } }
注意:為防止惡意操作,一般模板方法都加上 final 關鍵詞。