模板設計模式在 Java 里是一種行為設計模式,它在抽象類里定義算法的骨架,把部分步驟的具體實現延遲到子類。如此一來,子類可以在不改變算法結構的基礎上,重新定義算法中的特定步驟。
模式組成
抽象類(Abstract Class):定義了算法的骨架,其中包含模板方法與抽象方法。模板方法是具體方法,它規定了算法的步驟,并且會調用抽象方法;抽象方法則由子類去實現。 ?
具體子類(Concrete Subclass):實現抽象類中的抽象方法,完成算法中特定步驟的具體操作。 代碼示例
下面是一個用 Java 實現模板設計模式的示例,以制作飲料為例:
// 抽象類
abstract class Beverage {// 模板方法,定義制作飲料的算法骨架public final void prepareBeverage() {boilWater();brew();pourInCup();addCondiments();}public void boilWater() {System.out.println("Boiling water");}public void pourInCup() {System.out.println("Pouring into cup");}// 抽象方法,由子類實現public abstract void brew();public abstract void addCondiments();
}// 具體子類:咖啡
class Coffee extends Beverage {@Overridepublic void brew() {System.out.println("Dripping coffee through filter");}@Overridepublic void addCondiments() {System.out.println("Adding sugar and milk");}
}// 具體子類:茶
class Tea extends Beverage {@Overridepublic void brew() {System.out.println("Steeping the tea");}@Overridepublic void addCondiments() {System.out.println("Adding lemon");}
}// 測試類
public class TemplatePatternDemo {public static void main(String[] args) {Beverage coffee = new Coffee();System.out.println("Making coffee:");coffee.prepareBeverage();System.out.println("\nMaking tea:");Beverage tea = new Tea();tea.prepareBeverage();}
}
代碼解釋
Beverage類屬于抽象類,prepareBeverage方法是模板方法,它定義了制作飲料的通用步驟。brew和addCondiments是抽象方法,要由子類來實現。
Coffee和Tea類為具體子類,它們實現了brew和addCondiments方法,完成了制作咖啡和茶的特定步驟。
優點
代碼復用:模板方法定義了算法的骨架,避免了在多個子類中重復編寫相同的代碼。
可擴展性:子類能夠根據需求重寫抽象方法,實現自身的業務邏輯。
缺點
類數量增加:每一個不同的實現都需要一個子類,這可能會導致類的數量增加,使系統更加復雜。 靈活性受限:由于模板方法定義了算法的骨架,子類只能在特定的步驟上進行擴展,可能會限制算法的靈活性。
public final void prepareBeverage(),final修飾里面的方法,不能重寫,里面的方法卻能重寫,我很混亂,通俗易懂解釋一下
在模板方法模式中,prepareBeverage()
?被聲明為?final
?是為了確保算法的整體流程不被子類修改,而內部的?brew()
?和?addCondiments()
?被聲明為?abstract
?是為了強制子類實現具體的細節。這種設計實現了“固定流程,靈活擴展”的效果。
通俗解釋:
-
為什么用?
final
?
prepareBeverage()
?是制作飲料的固定流程(燒水 → 沖泡 → 倒杯 → 加調料),用?final
?表示“這個流程不能被子類篡改”。比如,子類不能把順序改成“先加調料再燒水”。 -
為什么內部的?
brew()
?和?addCondiments()
?可以重寫?
這兩個方法是抽象方法(abstract
),子類必須實現它們。父類只定義流程(“要沖泡”和“要加調料”),但具體怎么沖泡、加什么調料,由子類自己決定。例如:-
咖啡沖泡是“用濾紙滴漏”,加“糖和牛奶”。
-
茶沖泡是“用熱水浸泡茶葉”,加“檸檬”。
-
類比現實場景:
想象一個“烹飪機器人”的模板:
-
固定流程(
final
?方法):
它的做菜步驟是固定的:開火 → 放食材 → 翻炒 → 關火。 -
靈活擴展(抽象方法):
但具體“放什么食材”、“怎么翻炒”由用戶決定(比如做西紅柿炒蛋還是青椒肉絲)。
代碼驗證:
如果子類嘗試重寫?prepareBeverage()
,會直接編譯報錯:
class Coffee extends Beverage {// ? 編譯錯誤!不能重寫 final 方法@Overridepublic void prepareBeverage() { // 非法操作!}
}
但子類必須實現抽象方法:
class Coffee extends Beverage {@Overridepublic void brew() { /* 必須實現 */ } // ?@Overridepublic void addCondiments() { /* 必須實現 */ } // ?
}
總結:
-
final
?方法:保護算法流程的完整性(“怎么做”)。 -
abstract
?方法:定義子類必須實現的擴展點(“做什么”)。
這就是模板方法模式的核心:在父類控制流程,在子類實現細節。