简介
假设你要冲泡咖啡和茶,两者的流程相似但部分步骤不同:
- 烧水(公共步骤)
- 加入主材料(咖啡粉/茶叶)
- 添加调料(糖/牛奶)→ 可选步骤
- 倒进杯子(公共步骤)
模板模式的作用:
- 在父类中定义冲泡饮料的固定流程(如烧水、倒杯),子类只需实现差异步骤(如加咖啡粉或茶叶)。
- 避免重复代码,同时允许灵活扩展(如是否加调料)。
适用场景:
- 多个类有相同流程,但某些步骤实现不同(如数据处理、文件解析)。
- 需要控制子类的扩展点(如钩子方法)。
优点:
- 代码复用:公共逻辑在父类实现。
- 灵活扩展:子类只需关注差异步骤。
缺点:
- 父类定义流程,子类可能被限制灵活性。
- 容易因父类修改影响所有子类。
代码
// 抽象模板类:定义饮料冲泡流程
abstract class BeverageTemplate {
// 模板方法(final 防止子类覆盖)
public final void prepareBeverage() {
boilWater();
brew();
addCondiments(); // 钩子方法(可选步骤)
pourInCup();
}
// 公共步骤
private void boilWater() {
System.out.println("烧水");
}
private void pourInCup() {
System.out.println("倒进杯子");
}
// 抽象方法:子类必须实现
protected abstract void brew();
// 钩子方法(默认不添加调料,子类可选覆盖)
protected void addCondiments() {}
}
// 具体子类:咖啡
class Coffee extends BeverageTemplate {
protected void brew() {
System.out.println("加入咖啡粉");
}
@Override
protected void addCondiments() {
System.out.println("加糖和牛奶");
}
}
// 具体子类:茶
class Tea extends BeverageTemplate {
protected void brew() {
System.out.println("加入茶叶");
}
}
// 客户端代码
public class Client {
public static void main(String[] args) {
BeverageTemplate coffee = new Coffee();
coffee.prepareBeverage();
// 输出:
// 烧水 → 加入咖啡粉 → 加糖和牛奶 → 倒进杯子
BeverageTemplate tea = new Tea();
tea.prepareBeverage();
// 输出:
// 烧水 → 加入茶叶 → 倒进杯子
}
}
类图
@startuml
abstract class BeverageTemplate {
+ prepareBeverage(): void
- boilWater(): void
- pourInCup(): void
# brew(): void
# addCondiments(): void
}
class Coffee {
# brew(): void
# addCondiments(): void
}
class Tea {
# brew(): void
}
BeverageTemplate <|-- Coffee
BeverageTemplate <|-- Tea
@enduml
场景
数据库连接、执行SQL、关闭连接的固定流程。
// 抽象模板类
public abstract class JdbcTemplate {
// 模板方法
public final void execute() {
connect();
String sql = buildSql(); // 抽象方法
executeSql(sql);
close();
}
private void connect() {
System.out.println("连接数据库");
}
private void executeSql(String sql) {
System.out.println("执行SQL: " + sql);
}
private void close() {
System.out.println("关闭连接");
}
protected abstract String buildSql();
}
// 具体子类:用户查询
class UserQuery extends JdbcTemplate {
protected String buildSql() {
return "SELECT * FROM users";
}
}
// 具体子类:订单插入
class OrderInsert extends JdbcTemplate {
protected String buildSql() {
return "INSERT INTO orders VALUES (...)";
}
}
// 客户端代码
public class DatabaseClient {
public static void main(String[] args) {
JdbcTemplate userQuery = new UserQuery();
userQuery.execute();
// 输出:
// 连接数据库 → 执行SQL: SELECT * FROM users → 关闭连接
JdbcTemplate orderInsert = new OrderInsert();
orderInsert.execute();
// 输出:
// 连接数据库 → 执行SQL: INSERT INTO orders... → 关闭连接
}
}