模板方法模式是一种行为型设计模式,在Java中通常通过抽象类来体现。它的核心思想是:父类定义好一个算法的执行步骤(模板方法),把其中可能变化的具体步骤声明为抽象方法或部分实现的方法,交给子类去完成。这样既能保证整体流程稳定,又能让不同子类有自己的实现细节。

模板方法模式的基本结构
在Java里,模板方法模式一般包含两个部分:抽象父类和具体子类。抽象父类里有一个用final修饰的模板方法,它按固定顺序调用其他普通方法或抽象方法;子类继承后只重写需要变化的步骤。
代码示例
下面用一个冲泡饮料的例子来说明。无论是泡茶还是冲咖啡,步骤都是烧水、冲泡、倒杯、加料,其中冲泡和加料不同。
// 抽象父类,定义模板方法
public abstract class Beverage {
// 模板方法,用final防止子类修改整体流程
public final void prepare() {
boilWater();
brew();
pourInCup();
if (needCondiment()) {
addCondiment();
}
}
private void boilWater() {
System.out.println("烧开水");
}
private void pourInCup() {
System.out.println("倒入杯中");
}
// 抽象方法,由子类实现
protected abstract void brew();
// 抽象方法,由子类实现
protected abstract void addCondiment();
// 钩子方法,默认返回true,子类可覆盖
protected boolean needCondiment() {
return true;
}
}
// 具体子类:茶
public class Tea extends Beverage {
protected void brew() {
System.out.println("用热水泡茶");
}
protected void addCondiment() {
System.out.println("加柠檬");
}
}
// 具体子类:咖啡
public class Coffee extends Beverage {
protected void brew() {
System.out.println("冲泡咖啡粉");
}
protected void addCondiment() {
System.out.println("加糖和奶");
}
protected boolean needCondiment() {
return false; // 咖啡不加料
}
}
钩子方法的作用
上面代码中的needCondiment()就是一个钩子方法。它在父类中提供默认实现,子类可以选择重写来控制模板方法里的分支逻辑,而不必改动主流程。
模板方法模式的优点
- 减少重复代码,公共逻辑放在父类
- 符合开闭原则,新增子类很容易
- 框架源码中常见,如Servlet的service方法
使用时的注意点
模板方法一般用final修饰以防止子类破坏算法结构;抽象步骤用protected而不是public,避免外部直接调用。如果变化点太多,就要考虑是否改用策略模式更合适。