模板方法模式的核心是抽象类定义算法骨架,模板方法必须声明为final,通过public final execute()统一入口调用protected abstract方法或钩子方法,严格区分强制实现与可选覆盖,遵循好莱坞原则解耦流程与实现。

在 Java 继承体系中设计规范的模板方法模式,核心是用抽象类定义算法骨架,把不变逻辑固化、可变部分交给子类填空,同时严格控制扩展边界——不是“写个方法让子类继承”,而是提前规划流程、明确职责、锁死主干。
模板方法必须声明为 final
这是最易忽略却最关键的一点。模板方法代表整个算法的执行顺序和控制权,一旦允许子类重写,流程就可能被跳过、打乱甚至替换。正确做法是:
- 用 public final void execute() 作为统一入口
- 内部只调用 protected abstract 方法(强制实现)或 protected 钩子方法(可选覆盖)
- 避免在模板方法里调用 public 方法,防止外部绕过流程直接触发未完成步骤
合理区分抽象方法与钩子方法
语义不同,强制性也不同,不能混用:
- 抽象方法:用于核心不可省略的步骤,比如参数校验、数据加载、结果封装。子类不实现,编译直接报错
- 钩子方法:用于辅助性、可选行为,如日志记录、缓存清理、异步通知。提供空实现(protected void beforeProcess() {}),子类按需覆盖
- 典型命名如 beforeProcess()、afterSuccess()、shouldRetry(),既清晰又支持流程干预
父类不硬编码子类,子类不反向驱动流程
模板方法存在的意义是解耦流程与实现,不是为了方便父类调用具体子类:
- 禁止在抽象类的 execute() 中写 new ConcreteExportToExcel() 这类代码——破坏多态性,违反开闭原则
- 子类不该主动调用 super.templateMethod()。真正的协作是“父类调用子类”,体现好莱坞原则:Don’t call us, we’ll call you
- 客户端决定实例化哪个子类,再调用继承来的模板方法;子类只负责填充抽象方法、选择性覆盖钩子
新增扩展优先用钩子,慎加抽象方法
在已有抽象类中新增 abstract 方法,会导致所有子类编译失败,这是高风险反模式:
- 新增功能应优先使用钩子方法(protected + 默认空实现)
- 若逻辑差异较大,考虑拆出新抽象类,让老子类继续继承旧类,新子类继承新类
- 避免把扩展成本转嫁给所有下游,保持演进可控
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











