模板方法模式通过抽象类抽取公共流程,将稳定骨架固化为final模板方法,可变步骤声明为abstract方法,可选定制点设为protected钩子方法,并推荐接口与抽象类组合使用以提升灵活性。

抽象类模板方法抽取公共流程,核心是识别“稳定不变的骨架”和“可变的具体步骤”,把前者固化在父类中,后者留给子类实现。
先梳理业务流程,区分哪些该固定、哪些该放开
比如订单导出功能,整体流程通常是:连接数据源 → 获取数据 → 格式化数据 → 写入文件。其中“连接数据源”“获取数据”“写入文件”在多数场景下逻辑一致;而“格式化数据”因导出类型(Excel/CSV/JSON)不同差异明显。这类差异点就是该抽成抽象方法的地方。
- 固定部分 → 写成具体方法(甚至 private 或 final)
- 变化部分 → 声明为 protected abstract 方法
- 可选定制点 → 定义为 protected 钩子方法(空实现或默认行为)
模板方法本身必须是 final,防止流程被破坏
模板方法(如 export()、play())是整个流程的入口,它按顺序调用各步骤。一旦允许子类重写,就可能跳过校验、颠倒顺序、漏掉关键操作——这会破坏骨架意义。
- 用 public final void export() 明确禁止覆盖
- 内部只调用本类的方法(抽象的、具体的、钩子的),不暴露流程控制权
- 避免在构造器里调用任何可能被子类重写的方法
把通用逻辑下沉,但别强求“全抽象”
常见误区是把所有方法都标成 abstract,结果子类被迫重写日志、空校验、基础参数检查等本可复用的代码。其实:
- 事务开启、连接关闭、异常统一包装 → 放父类具体方法
- 字段校验规则、权限检查、幂等处理 → 可作为 protected 钩子,默认通过,子类按需覆盖
- 真正因业务而异的环节(如折扣计算、状态转换策略、序列化方式)→ 才设为 abstract
用接口 + 抽象类组合,更灵活
如果多个类有共同流程,但又不属于同一继承体系(比如订单导出和用户导出没有父子关系),可以:
- 定义一个 Exportable 接口,声明
export()行为契约 - 提供一个 AbstractExporter 抽象类,含完整模板方法和通用实现
- 各导出类继承该抽象类,专注实现 formatData() 等抽象方法
这样既复用骨架,又不强绑继承层级。










