模板方法模式(Template Method) - 最易懂的設計模式解析
前言
今天我來全面總結一下Android開發中最常用的設計模式 - 模板方法模式。
目錄

1.jpg
1. 介紹
1.1 定義
定義一個模板結構,將具體內容延遲到子類去實現。
1.2 主要作用
在不改變模板結構的前提下在子類中重新定義模板中的內容。
模板方法模式是基於”繼承“的;
1.3 解決的問題
- 提高程式碼複用性
將相同部分的程式碼放在抽象的父類中,而將不同的程式碼放入不同的子類中 - 實現了反向控制
通過一個父類呼叫其子類的操作,通過對子類的具體實現擴充套件不同的行為,實現了反向控制 & 符合“開閉原則”
2. 模式原理
2.1 UML類圖 & 組成

1.png
2.2 例項講解
接下來我用一個例項來對模板方法模式進行更深一步的介紹。
a. 例項概況
背景:小成希望學炒菜:手撕包菜 & 蒜蓉炒菜心
衝突:兩道菜的炒菜步驟有的重複有的卻差異很大,記不住
解決方案:利用程式碼記錄下來
b. 使用步驟
步驟1: 建立抽象模板結構(Abstract Class):炒菜的步驟
publicabstract class Abstract Class { //模板方法,用來控制炒菜的流程 (炒菜的流程是一樣的-複用) //申明為final,不希望子類覆蓋這個方法,防止更改流程的執行順序 final void cookProcess(){ //第一步:倒油 this.pourOil(); //第二步:熱油 this.HeatOil(); //第三步:倒蔬菜 this.pourVegetable(); //第四步:倒調味料 this.pourSauce(); //第五步:翻炒 this.fry(); } //定義結構裡哪些方法是所有過程都是一樣的可複用的,哪些是需要子類進行實現的 //第一步:倒油是一樣的,所以直接實現 void pourOil(){ System.out.println("倒油"); } //第二步:熱油是一樣的,所以直接實現 voidHeatOil(){ System.out.println("熱油"); } //第三步:倒蔬菜是不一樣的(一個下包菜,一個是下菜心) //所以宣告為抽象方法,具體由子類實現 abstract voidpourVegetable(); //第四步:倒調味料是不一樣的(一個下辣椒,一個是下蒜蓉) //所以宣告為抽象方法,具體由子類實現 abstract voidpourSauce(); //第五步:翻炒是一樣的,所以直接實現 void fry();{ System.out.println("炒啊炒啊炒到熟啊"); } }
步驟2: 建立具體模板(Concrete Class),即”手撕包菜“和”蒜蓉炒菜心“的具體步驟
//炒手撕包菜的類 public class ConcreteClass_BaoCai extendAbstract Class{ @Override public voidpourVegetable(){ System.out.println(”下鍋的蔬菜是包菜“); } @Override public voidpourSauce(){ System.out.println(”下鍋的醬料是辣椒“); } } //炒蒜蓉菜心的類 public class ConcreteClass_CaiXin extendAbstract Class{ @Override public voidpourVegetable(){ System.out.println(”下鍋的蔬菜是菜心“); } @Override public voidpourSauce(){ System.out.println(”下鍋的醬料是蒜蓉“); } }
步驟3: 客戶端呼叫-炒菜了
public class Template Method{ public static void main(String[] args){ //炒 - 手撕包菜 ConcreteClass_BaoCai BaoCai = new ConcreteClass_BaoCai(); BaoCai.cookProcess(); //炒 - 蒜蓉菜心 ConcreteClass_ CaiXin = new ConcreteClass_CaiXin(); CaiXin.cookProcess(); } }
結果輸出
倒油 熱油 下鍋的蔬菜是包菜 下鍋的醬料是辣椒 炒啊炒啊炒到熟 倒油 熱油 下鍋的蔬菜是菜心 下鍋的醬料是蒜蓉 炒啊炒啊炒到熟
通過上述這個常見的生活例子,我相信你已經完全明白了模板方法模式的原理了!!
3. 優缺點
在全面解析完模板方法模式後,我來分析下其優缺點:
3.1 優點
- 提高程式碼複用性
將相同部分的程式碼放在抽象的父類中 - 提高了拓展性
將不同的程式碼放入不同的子類中,通過對子類的擴充套件增加新的行為 - 實現了反向控制
通過一個父類呼叫其子類的操作,通過對子類的擴充套件增加新的行為,實現了反向控制 & 符合“開閉原則”
3.2 缺點
引入了抽象類,每一個不同的實現都需要一個子類來實現,導致類的個數增加,從而增加了系統實現的複雜度。
4. 應用場景
- 一次性實現一個演算法的不變的部分,並將可變的行為留給子類來實現;
- 各子類中公共的行為應被提取出來並集中到一個公共父類中以避免程式碼重複;
- 控制子類的擴充套件。