WHAT

定义

Define eht skeleton of an algorithm in an operation, deferring some steps to subclasses. Template Method lets subclasses redefine certain steps of an algorithm without changing the algorithm's structure.

定义一个操作中的算法的框架,而将一些步骤延迟到子类中。使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。

类图

AbstractClass - 抽象模板

  • 基本方法

    基本操作,是由子类实现的方法,并且在模板方法中被调用

  • 模板方法

    可以有一个或几个,一般是一个具体方法,也就是一个框架,实现对基本方法的调度,完成固定的逻辑

ConcreteClass - 具体模板

实现父类所定义的一个或多个抽象方法,使得父类定义的基本方法在子类中得以实现。

WHY

优势

  • 封装不变部分,扩展可变部分
    • 不变部分的算法封装到父类实现
    • 可变部分的则通过集成来继续扩展
  • 提取公共部分代码,便于维护
  • 行为由父类控制,子类实现
    • 基本方法是由子类实现的,因此子类可以通过空战的方式增加响应的功能,符合开闭原则

劣势

  • 按照设计习惯,抽象类负责声明最抽象、最一般的事务属性和方法,实现类完成具体的事物属性和方法,但是模板方法模式颠倒了,抽象类定义部分抽象方法,子类实现,且子类的执行结果影响父类的结果。
  • 增加代码阅读的难度,对新手不友好

HOW

使用场景

  • 多个子类有公用的方法,并且逻辑基本相同时
  • 重要、复杂的算法,可以把核心算法设计为模板方法,周边相关的细节功能则由各个子类实现
  • 重构时,模板方法模式是一个经常使用的模式,把相同的代码抽取到父类中,然后通过狗子函数约束其行为。

扩展

钩子函数

在父类中增加抽象的基本方法,在子类中进行返回自定义的值。且通过子类对象可以对该值进行修改。在父类的模板方法中,使用了改基本方法进行控制模板方法的执行流程。

这样实现由子类的一个方法返回决定公共部分的执行结果。

最佳实践

模板方法模式可以实现父类依赖子类,子类影响父类行为的结果的效果。

注意事项

  • 为了防止恶意的操作,一般模板方法都加上final官架子,不允许被覆写。
  • 抽象模板中的基本方法尽量设计为protected类型,符合迪米特法则,不需要暴露的属性或方法尽量不要设置为protected类型,实现类若非必要,尽量不要扩大父类中的访问权限。
  • 在软件开发过程中,如果相同的一段代码复制过两次,就需要对设计产生怀疑,架构师要明确地说明为什么相同的逻辑要出现两次或更多次

《设计模式之禅》第十章 模板方法模式