目錄
一、模板方法模式
1、結構
2、特性
3、優缺點
3.1、優點
3.2、缺點
4、使用場景
5、實現示例
5.1、抽象類
5.2、實現類
5.3、測試類
一、模板方法模式
模板方法模式(Template Method Pattern)是一種行為設計模式,它在一個方法中定義了一個算法的骨架,而將一些步驟的實現延遲到子類中。
通過這種方式,模板方法模式可以將步驟的執行順序控制在父類中,同時允許子類覆蓋特定步驟的實現以滿足具體需要。
1、結構
模板方法模式包含以下主要角色:
-
抽象類(Abstract Class)
-
定義抽象的基本操作,子類將重定義它們以實現算法的特定步驟
-
實現一個模板方法,定義算法的骨架
-
-
具體類(Concrete Class)
-
實現基本操作以完成算法中與特定子類相關的步驟
-
2、特性
? ? 固定算法結構:模板方法通過定義算法的骨架,確保算法的固定執行順序。
? ? 可擴展步驟:子類可以覆蓋父類中定義的抽象方法,從而擴展或修改某些步驟,而不影響整體算法的結構。
? ? 不可變模板方法:模板方法通常使用 final 修飾,這樣子類就不能重寫這個方法,從而保證了算法骨架的穩定性。
3、優缺點
3.1、優點
? ? 代碼復用:通過在抽象類中定義公用的算法結構,可以減少代碼重復,提高代碼復用性。
? ? 靈活性和可擴展性:子類可以根據具體需求覆蓋抽象方法,從而實現不同的具體行為,這提高了系統的靈活性和可擴展性。
? ? 控制反轉:模板方法模式實現了一種變相的控制反轉,由父類調用子類實現的具體方法,減少了子類對父類的依賴。
3.2、缺點
? ? 過度設計:如果算法步驟很簡單或變化不大,使用模板方法模式可能導致過度設計,引入不必要的復雜性。
? ? 實現不直觀:模板方法模式涉及繼承和多態,對某些人來說可能不是特別直觀,需要詳細文檔說明才能正確理解和使用。
4、使用場景
-
一次性實現算法的不變部分,將可變部分留給子類實現
-
各子類中公共的行為應被提取出來集中到公共父類中
-
控制子類擴展,只允許在特定點進行擴展
5、實現示例
5.1、抽象類
?
/*** 抽象類 - 飲料制作模板* 定義了制作飲料的算法骨架*/
public abstract class BeverageTemplate {// 模板方法 - 定義制作飲料的步驟(算法骨架)public final void prepareBeverage() {boilWater();brew();pourInCup();if (customerWantsCondiments()) {addCondiments();}}// 具體方法 - 燒水(所有飲料都一樣)private void boilWater() {System.out.println("燒開水");}// 具體方法 - 倒入杯子(所有飲料都一樣)private void pourInCup() {System.out.println("將飲料倒入杯子");}// 抽象方法 - 沖泡(由子類實現)protected abstract void brew();// 抽象方法 - 添加調料(由子類實現)protected abstract void addCondiments();// 鉤子方法 - 顧客是否要加調料(默認返回true,子類可覆蓋)protected boolean customerWantsCondiments() {return true;}
}
5.2、實現類
具體子類 - 咖啡
/*** 具體子類 - 咖啡*/
public class Coffee extends BeverageTemplate {@Overrideprotected void brew() {System.out.println("沖泡咖啡粉");}@Overrideprotected void addCondiments() {System.out.println("加入糖和牛奶");}// 覆蓋鉤子方法 - 詢問用戶是否要加調料@Overrideprotected boolean customerWantsCondiments() {String answer = getUserInput();return answer.toLowerCase().startsWith("y");}}
具體子類 - 茶
/*** 具體子類 - 茶*/
public class Tea extends BeverageTemplate {@Overrideprotected void brew() {System.out.println("浸泡茶葉");}@Overrideprotected void addCondiments() {System.out.println("加入檸檬");}// 覆蓋鉤子方法 - 茶默認不加調料@Overrideprotected boolean customerWantsCondiments() {return false;}
}
5.3、測試類
public class BeverageTest {public static void main(String[] args) {System.out.println("======= 制作咖啡 =======");BeverageTemplate coffee = new Coffee();coffee.prepareBeverage();System.out.println("\n======= 制作茶 =======");BeverageTemplate tea = new Tea();tea.prepareBeverage();}
}
結果:
======= 制作咖啡 =======
燒開水
沖泡咖啡粉
將飲料倒入杯子
您的咖啡要加糖和牛奶嗎 (y/n)? y
加入糖和牛奶======= 制作茶 =======
燒開水
浸泡茶葉
將飲料倒入杯子