抽象类是实现模板方法模式最自然的方式,通过final模板方法固定算法骨架,用abstract方法强制子类实现差异逻辑,以hook方法提供可选扩展点,确保流程稳定且易于扩展。

抽象类是实现模板方法设计模式最自然、最常用的方式。核心思路是:在抽象类中定义算法骨架(即模板方法),把某些步骤延迟到子类中实现,从而在不改变算法结构的前提下,允许子类重新定义该算法的某些特定步骤。
定义抽象模板类,封装不变逻辑
模板方法本身必须是 final 的(防止子类覆盖算法流程),而可变步骤则声明为 abstract 或提供默认空实现(hook 方法)。这样既保证流程稳定,又保留扩展点。
- 模板方法(如
execute())包含完整执行顺序,调用多个钩子方法 - 抽象方法(如
doStep1()、doStep2())强制子类实现关键差异逻辑 - 钩子方法(如
isLoggingEnabled())可选重写,默认返回 false 或空操作
子类继承并实现具体步骤
子类只需覆写抽象方法,无需关心整体流程。例如处理订单的模板:validate() → processPayment() → ship() → sendNotification(),每个环节由不同子类按渠道定制(如微信支付、银行卡支付),但“先校验再支付再发货”这个顺序始终不变。
- 子类不能改变模板方法的调用顺序,只能填充内容
- 可选择性覆写 hook 方法来微调行为(比如只在测试环境记录日志)
- 避免在子类中直接调用模板方法,否则可能引发递归或流程错乱
注意访问控制与设计意图对齐
模板方法内部调用的抽象方法通常设为 protected,确保仅对子类可见;模板方法本身用 public final 对外暴露;构造逻辑若需预处理,可在抽象类构造器中完成,但要避免调用可被子类重写的方法(防止初始化时发生多态调用异常)。
立即学习“Java免费学习笔记(深入)”;
- 不要在抽象类构造器中调用 abstract 方法
- 避免将模板方法设为 static,否则无法利用多态分发子类实现
- 必要时可用
final修饰某些 hook 方法,防止子类误改关键判断逻辑
配合钩子方法增强灵活性
除了强制实现的抽象方法,还可以定义非抽象的钩子方法(hook),提供默认行为,让子类按需覆盖。比如 beforeExecute() 和 afterExecute() 可用于统一加日志、统计耗时、清理资源等,而不需要每个子类都重复写 try-finally。
- 钩子方法默认为空实现或返回固定值,降低子类实现负担
- 典型场景包括:前置校验、后置清理、失败回调、性能埋点
- 比直接在模板方法里写 if-else 更符合开闭原则


















