模板方法模式是**基於繼承的代碼復用核心技術**,屬於類行為型模式。它將算法的**不變部分**封裝在父類模板方法中,**可變部分**抽象為基本方法由子類實現,實現「好萊塢原則」:Don't call us, we'll call you。
| 角色 | 職責 | 關鍵點 |
|---|---|---|
| 抽象模板 | 1. 定義抽象基本方法 (強制子類實現) 2. 實現模板方法 (最終 final,調用基本方法組裝算法骨架) 3. 可提供鉤子方法 (空實現,子類可選覆寫) | 算法骨架守護者,控制流程順序 |
| 具體模板 | 實現父類抽象基本方法,提供差異化邏輯 | 每個具體類對應一種算法變體 |
public abstract class Animal {
// 基本方法:抽象,強制子類實現
public abstract String info();
// 模板方法:final 禁止覆寫,鎖定算法骨架
public final void show() {
System.out.println(info() + "我是最聰明的動物");
}
}
public class Cat extends Animal {
@Override public String info() { return "我是一只貓"; }
}
public class Dog extends Animal {
@Override public String info() { return "我是一條狗"; }
}
public class Test {
public static void main(String[] args) {
Animal a1 = new Dog(); a1.show(); // 我是一條狗我是最聰明的動物
Animal a2 = new Cat(); a2.show(); // 我是一只貓我是最聰明的動物
}
}
| 類型 | 關鍵字 | 實現者 | 子類可否覆寫 | 用途 |
|---|---|---|---|---|
| 抽象方法 | abstract | 子類**必須**實現 | 是 (強制) | 算法核心差異步驟 |
| 具體方法 | 無/ final | 父類實現 | 否 (建議 final) | 算法通用固定步驟 |
| 鉤子方法 | 無/ protected | 父類提供空/默認實現 | 是 (可選) | 算法可選擴展點、條件判斷 |
public abstract class ReportGenerator {
// 模板方法
public final void generate() {
collectData();
if (needChart()) { // 鉤子方法控制流程
buildChart();
}
renderReport();
}
protected abstract void collectData(); // 抽象方法
protected abstract void renderReport(); // 抽象方法
protected void buildChart() { // 具體方法
System.out.println("構建通用圖表...");
}
protected boolean needChart() { // 鉤子方法:默認 true
return true;
}
}
public class SimpleReport extends ReportGenerator {
@Override protected void collectData() { System.out.println("收集簡易數據"); }
@Override protected void renderReport() { System.out.println("渲染簡易報表"); }
@Override protected boolean needChart() { return false; } // 覆寫鉤子:不需要圖表
}
| 維度 | 模板方法 | 策略模式 |
|---|---|---|
| 核心機制 | 繼承 (is-a) | 組合/委派 (has-a) |
| 算法骨架位置 | 父類 (固定) | 上下文類 (可運行時切換) |
| 可變部分 | 子類重寫方法 | 策略接口實現類 |
| 擴展方式 | 新增子類 | 新增策略類 + 注入 |
| 耦合度 | 較高 (繼承耦合) | 較低 (接口耦合) |
| 適用場景 | 算法骨架穩定、變體較少、編譯時確定 | 算法族並存、需運行時動態切換 |
HttpServlet:service() 模板方法 → 分發 doGet()/doPost() (基本方法)AbstractList:addAll() 模板 → 循環調用 add() (基本方法)JdbcTemplate:execute() 模板 → 回調 PreparedStatementCallback (鉤子/回調)HibernateTemplate、RedisTemplate 等 Spring 模板類InputStream.read():模板方法調用抽象 read(byte[])needXxx()、beforeXxx()、afterXxx(),語義清晰模板方法模式以**「父類定骨架、子類填肉」**的極簡哲學,解決了算法家族中**結構固定、細節多變**的經典問題。它是框架設計的基石(JDK、Spring 大量應用),也是理解「控制反轉」最直觀的入門模式。掌握其**三種基本方法分類、final 鎖定骨架、鉤子方法靈活控制流**,即可在框架擴展、業務流程標準化、代碼去重場景中遊刃有餘。