一、 介紹
①、定義
定義一個模板結構,將具體內容延遲到子類去實現。
②、主要作用
在不改變模板結構的前提下在子類中重新定義模板中的內容。
模板方法模式是基於”繼承“的;
③、解決的問題
- 提高代碼複用性
將相同部分的代碼放在抽象的父類中,而將不同的代碼放入不同的子類中 - 實現了反向控制
通過一個父類調用其子類的操作,通過對子類的具體實現擴展不同的行爲,實現了反向控制 & 符合“開閉原則”
二、 模式原理
①、UML類圖 & 組成
②、實例講解
接下來我用一個實例來對模板方法模式進行更深一步的介紹。
a. 實例概況
- 背景:小成希望學炒菜:手撕包菜 & 蒜蓉炒菜心
- 衝突:兩道菜的炒菜步驟有的重複有的卻差異很大,記不住
- 解決方案:利用代碼記錄下來
b. 使用步驟
步驟1: 創建抽象模板結構(Abstract Class):炒菜的步驟
public abstract class Abstract Class {
//模板方法,用來控制炒菜的流程 (炒菜的流程是一樣的-複用)
//申明爲final,不希望子類覆蓋這個方法,防止更改流程的執行順序
final void cookProcess(){
//第一步:倒油
this.pourOil();
//第二步:熱油
this.HeatOil();
//第三步:倒蔬菜
this.pourVegetable();
//第四步:倒調味料
this.pourSauce();
//第五步:翻炒
this.fry();
}
//定義結構裏哪些方法是所有過程都是一樣的可複用的,哪些是需要子類進行實現的
//第一步:倒油是一樣的,所以直接實現
void pourOil(){
System.out.println("倒油");
}
//第二步:熱油是一樣的,所以直接實現
void HeatOil(){
System.out.println("熱油");
}
//第三步:倒蔬菜是不一樣的(一個下包菜,一個是下菜心)
//所以聲明爲抽象方法,具體由子類實現
abstract void pourVegetable();
//第四步:倒調味料是不一樣的(一個下辣椒,一個是下蒜蓉)
//所以聲明爲抽象方法,具體由子類實現
abstract void pourSauce();
//第五步:翻炒是一樣的,所以直接實現
void fry();{
System.out.println("炒啊炒啊炒到熟啊");
}
}
步驟2: 創建具體模板(Concrete Class),即”手撕包菜“和”蒜蓉炒菜心“的具體步驟
//炒手撕包菜的類
public class ConcreteClass_BaoCai extend Abstract Class{
@Override
public void pourVegetable(){
System.out.println(”下鍋的蔬菜是包菜“);
}
@Override
public void pourSauce(){
System.out.println(”下鍋的醬料是辣椒“);
}
}
//炒蒜蓉菜心的類
public class ConcreteClass_CaiXin extend Abstract Class{
@Override
public void pourVegetable(){
System.out.println(”下鍋的蔬菜是菜心“);
}
@Override
public void pourSauce(){
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();
}
}
結果輸出
倒油
熱油
下鍋的蔬菜是包菜
下鍋的醬料是辣椒
炒啊炒啊炒到熟
倒油
熱油
下鍋的蔬菜是菜心
下鍋的醬料是蒜蓉
炒啊炒啊炒到熟
通過上述這個常見的生活例子,我相信你已經完全明白了模板方法模式的原理了!!
三、 優缺點
在全面解析完模板方法模式後,我來分析下其優缺點:
①、優點
- 提高代碼複用性
將相同部分的代碼放在抽象的父類中 - 提高了拓展性
將不同的代碼放入不同的子類中,通過對子類的擴展增加新的行爲 - 實現了反向控制
通過一個父類調用其子類的操作,通過對子類的擴展增加新的行爲,實現了反向控制 & 符合“開閉原則”
②、缺點
引入了抽象類,每一個不同的實現都需要一個子類來實現,導致類的個數增加,從而增加了系統實現的複雜度。
四、應用場景
- 一次性實現一個算法的不變的部分,並將可變的行爲留給子類來實現;
- 各子類中公共的行爲應被提取出來並集中到一個公共父類中以避免代碼重複;
- 控制子類的擴展。
轉載自 : https://blog.csdn.net/carson_ho/article/details/54910518