• 在超类中定义了一个算法的框架,允许子类栽不修改结构的情况下重写算法的特定步骤。

例子
分析各种类型的文档 (PDF、 DOC 或 CSV) ,提取出有意义的信息,以统一的格式返回给用户。

模板模式 - 图1

三个类中包含许多相似代码。 尽管这些类处理不同数据格式的代码完全不同, 但数据处理和分析的代码却几乎完全一样。

步骤

模板方法模式建议将算法分解为一系列步骤, 然后将这些步骤改写为方法, 最后在 “模板方法” 中依次调用这些方法。

步骤可以是 抽象的, 也可以有一些默认的实现。 为了能够使用算法, 客户端需要自行提供子类并实现所有的抽象步骤。 如有必要还需重写一些步骤 (但这一步中不包括模板方法自身)。

模板模式 - 图2

  1. 将所有步骤声明为 抽象类型, 强制要求子类自行实现这些方法。
  2. 子类重写这些方法


钩子

例如某个部分是可选的,就可以使用勾子。
模板模式 - 图3
模板方法可用于建造大量房屋。

标准房屋建造方案中可提供几个扩展点, 允许潜在房屋业主调整成品房屋的部分细节。

每个建造步骤 (例如打地基、 建造框架、 建造墙壁和安装水电管线等) 都能进行微调, 这使得成品房屋会略有不同。

总结

模板模式 - 图4

  1. 抽象类 (Abstract­Class) 会声明作为算法步骤的方法, 以及依次调用它们的实际模板方法。 算法步骤可以被声明为 抽象类型, 也可以提供一些默认实现。

  2. 具体类 (Concrete­Class) 可以重写所有步骤, 但不能重写模板方法自身。

场景

只希望扩展某个特定算法步骤, 而不是整个算法或其结构时, 可使用模板方法模式。

  • 模板方法将整个算法转换为一系列独立的步骤, 以便子类能对其进行扩展, 同时还可让超类中所定义的结构保持完整。

当多个类的算法除一些细微不同之外几乎完全一样时, 你可使用该模式。 但其后果就是, 只要算法发生结构性变化, 你就可能需要修改所有的类。

  • 在将算法转换为模板方法时, 你可将相似的实现步骤提取到超类中以去除重复代码。 子类间各不同的代码可继续保留在子类中。

可用 final最终修饰模板方法以防止子类对其进行重写。

优点:
仅允许客户端重写一个大型算法中的特定部分, 使得算法其他部分修改对其所造成的影响减小。
可将重复代码提取到一个超类中。

缺点:
可能会受到算法框架的限制。
模板方法中的步骤越多, 其维护工作就可能会越困难。

对比

模板方法基于继承,通过扩展子类中的部分内容来改变部分算法。

  • 父类定义了一个算法大纲,子类定义其中的某些步骤的内容。

策略模式基于组合,以通过对相应行为提供不同的策略来改变对象的部分行为。

  • 定义了一个算法家族,让这些算法可以互换

模板方法在类层次上运作, 因此它是静态的。 策略在对象层次上运作, 因此允许在运行时切换行为。