模板方法模式 (Template Method)
📖 通俗理解
做菜的标准流程:
- 准备食材
- 放油热锅
- 放入食材(不同菜不同)
- 调味(不同菜不同)
- 出锅装盘
流程是固定的,但具体某些步骤因菜而异。
模板方法模式就是:定义一个操作的算法骨架,将某些步骤延迟到子类中实现。
🎯 解决什么问题?
多个类有相似的流程,只是某些步骤不同。把相同的部分提取到父类,不同的部分由子类实现。
🌰 生活中的例子
- 做菜流程:备菜 → 炒菜 → 出锅
- 考试流程:发卷 → 答题 → 收卷
- 面试流程:自我介绍 → 技术面 → HR 面
💻 Java 代码实现
场景:饮料制作
/**
* 抽象类:饮料模板
*/
public abstract class Beverage {
// 模板方法(final 防止子类修改流程)
public final void prepare() {
boilWater();
brew(); // 抽象方法,子类实现
pourInCup();
if (needCondiments()) { // 钩子方法
addCondiments();
}
}
private void boilWater() {
System.out.println("1. 烧开水");
}
// 抽象方法:冲泡
protected abstract void brew();
private void pourInCup() {
System.out.println("3. 倒入杯中");
}
// 抽象方法:加配料
protected abstract void addCondiments();
// 钩子方法:是否需要配料(子类可覆盖)
protected boolean needCondiments() {
return true;
}
}
/**
* 茶
*/
public class Tea extends Beverage {
@Override
protected void brew() {
System.out.println("2. 冲泡茶叶");
}
@Override
protected void addCondiments() {
System.out.println("4. 加柠檬");
}
}
/**
* 咖啡
*/
public class Coffee extends Beverage {
@Override
protected void brew() {
System.out.println("2. 冲泡咖啡");
}
@Override
protected void addCondiments() {
System.out.println("4. 加糖和牛奶");
}
}
/**
* 纯净水(不需要配料)
*/
public class PureWater extends Beverage {
@Override
protected void brew() {
System.out.println("2. 直接用矿泉水");
}
@Override
protected void addCondiments() {
// 不需要
}
@Override
protected boolean needCondiments() {
return false; // 覆盖钩子方法
}
}
使用:
public class Client {
public static void main(String[] args) {
System.out.println("=== 制作茶 ===");
Beverage tea = new Tea();
tea.prepare();
System.out.println("\n=== 制作咖啡 ===");
Beverage coffee = new Coffee();
coffee.prepare();
System.out.println("\n=== 纯净水 ===");
Beverage water = new PureWater();
water.prepare();
}
}
输出:
=== 制作茶 ===
1. 烧开水
2. 冲泡茶叶
3. 倒入杯中
4. 加柠檬
=== 制作咖啡 ===
1. 烧开水
2. 冲泡咖啡
3. 倒入杯中
4. 加糖和牛奶
=== 纯净水 ===
1. 烧开水
2. 直接用矿泉水
3. 倒入杯中
🔥 钩子方法
钩子方法(Hook):父类提供默认实现,子类可以选择性覆盖来影响流程。
// 钩子方法示例
protected boolean needCondiments() {
return true; // 默认需要配料
}
✅ 适用场景
- 多个类有相同的算法结构
- 需要控制子类扩展的点
- 提取公共代码,避免重复
📚 框架中的应用
- Spring:
JdbcTemplate - Servlet:
HttpServlet的service()方法 - JUnit:
setUp()和tearDown()
小结
模板方法模式:定义算法骨架,具体步骤由子类实现。
关键点:
- 模板方法定义流程(用 final 修饰)
- 抽象方法由子类实现
- 钩子方法让子类可选择性影响流程
👉 下一篇:访问者模式
