一、定义
模板方法模式定义一个算法的骨架,将一些步骤延迟到子类中实现。
子类可以重新定义算法的某些特定步骤,但不能改变算法的整体结构。
二、适用场景
- 有多个类具有相同的处理逻辑结构,但某些细节实现不同。
- 希望复用通用算法结构,并让子类专注实现细节。
- 需要对流程中的某些步骤进行扩展或自定义。
三、核心角色(Participants)
角色 | 说明 |
AbstractClass | 抽象模板类,定义算法结构和模板方法,包含抽象步骤方法 |
ConcreteClass | 具体子类,重写抽象步骤方法以自定义行为 |
四、UML 类图
┌────────────────────┐
│ AbstractClass │
│────────────────────│
│ + templateMethod() │ ← 模板方法(不能改)
│ - step1() │ ← 由父类实现或子类扩展
│ - step2() │ ← 抽象/可选步骤
└────────────────────┘
▲
│
┌────────────────────┐
│ ConcreteClassA │ ← 具体类实现
└────────────────────┘
五、真实业务场景:银行系统中的账户操作流程
🎯 背景说明:
银行系统中,每种账户类型(如储蓄账户、信用账户、企业账户)在处理“账户查询”时流程一致:
- 登录验证用户
- 查询账户数据
- 输出账户信息
但每种账户的“数据来源、查询权限”可能不同,这就适合使用模板方法模式。
六、代码实现(Java 示例)
✅ 1. 抽象模板类:AccountQueryService
public abstract class AccountQueryService {
// 模板方法:查询账户流程固定,不允许重写
public final void queryAccount() {
authenticate();
Object accountData = getAccountData();
printAccountData(accountData);
}
// 公共实现
private void authenticate() {
System.out.println("身份验证通过");
}
// 变动部分,由子类实现
protected abstract Object getAccountData();
// 可选钩子方法
protected void printAccountData(Object data) {
System.out.println("账户信息: " + data);
}
}
✅ 2. 具体子类:个人账户查询
public class PersonalAccountService extends AccountQueryService {
@Override
protected Object getAccountData() {
return "【个人账户】余额:¥12,345.67";
}
}
✅ 3. 具体子类:企业账户查询
public class EnterpriseAccountService extends AccountQueryService {
@Override
protected Object getAccountData() {
return "【企业账户】账户名:某某公司,授信额度:¥1,000,000";
}
@Override
protected void printAccountData(Object data) {
System.out.println("打印企业账户信息...");
System.out.println(data);
}
}
✅ 4. 客户端调用
public class Client {
public static void main(String[] args) {
AccountQueryService personal = new PersonalAccountService();
AccountQueryService enterprise = new EnterpriseAccountService();
System.out.println("===== 查询个人账户 =====");
personal.queryAccount();
System.out.println("\n===== 查询企业账户 =====");
enterprise.queryAccount();
}
}
七、优缺点分析
✅ 优点
- 封装流程控制逻辑,提高复用性
- 对子类开放扩展点(钩子方法)
- 遵循开闭原则:新增功能只需继承和重写部分方法
❌ 缺点
- 每新增一个流程变种就需要新增一个子类,可能导致类爆炸
- 如果步骤较多,维护成本上升
- 子类有可能重写过多,导致违背初衷
八、典型应用场景(补充)
场景 | 说明 |
JDK 中的 | 如 中定义模板方法 |
Spring 中的事务处理流程 |
|
网络请求框架 | 通用请求流程:前置处理、请求、响应解析、错误处理 |
🔚 总结一句话
模板方法模式通过“固定算法骨架 + 提供定制步骤”,实现了流程统一、行为可插拔的设计模式,特别适合“多个流程相似,部分逻辑不同”的场景。