- 在超类中定义了一个算法的框架,允许子类栽不修改结构的情况下重写算法的特定步骤。
例子
分析各种类型的文档 (PDF、 DOC 或 CSV) ,提取出有意义的信息,以统一的格式返回给用户。
三个类中包含许多相似代码。 尽管这些类处理不同数据格式的代码完全不同, 但数据处理和分析的代码却几乎完全一样。
步骤
模板方法模式建议将算法分解为一系列步骤, 然后将这些步骤改写为方法, 最后在 “模板方法” 中依次调用这些方法。
步骤可以是 抽象
的, 也可以有一些默认的实现。 为了能够使用算法, 客户端需要自行提供子类并实现所有的抽象步骤。 如有必要还需重写一些步骤 (但这一步中不包括模板方法自身)。
- 将所有步骤声明为
抽象
类型, 强制要求子类自行实现这些方法。 - 子类重写这些方法
钩子
例如某个部分是可选的,就可以使用勾子。
模板方法可用于建造大量房屋。
标准房屋建造方案中可提供几个扩展点, 允许潜在房屋业主调整成品房屋的部分细节。
每个建造步骤 (例如打地基、 建造框架、 建造墙壁和安装水电管线等) 都能进行微调, 这使得成品房屋会略有不同。
总结
抽象类 (AbstractClass) 会声明作为算法步骤的方法, 以及依次调用它们的实际模板方法。 算法步骤可以被声明为
抽象
类型, 也可以提供一些默认实现。具体类 (ConcreteClass) 可以重写所有步骤, 但不能重写模板方法自身。
场景
只希望扩展某个特定算法步骤, 而不是整个算法或其结构时, 可使用模板方法模式。
- 模板方法将整个算法转换为一系列独立的步骤, 以便子类能对其进行扩展, 同时还可让超类中所定义的结构保持完整。
当多个类的算法除一些细微不同之外几乎完全一样时, 你可使用该模式。 但其后果就是, 只要算法发生结构性变化, 你就可能需要修改所有的类。
- 在将算法转换为模板方法时, 你可将相似的实现步骤提取到超类中以去除重复代码。 子类间各不同的代码可继续保留在子类中。
可用 final
最终修饰模板方法以防止子类对其进行重写。
优点:
仅允许客户端重写一个大型算法中的特定部分, 使得算法其他部分修改对其所造成的影响减小。
可将重复代码提取到一个超类中。
缺点:
可能会受到算法框架的限制。
模板方法中的步骤越多, 其维护工作就可能会越困难。
对比
模板方法基于继承,通过扩展子类中的部分内容来改变部分算法。
- 父类定义了一个算法大纲,子类定义其中的某些步骤的内容。
策略模式基于组合,以通过对相应行为提供不同的策略来改变对象的部分行为。
- 定义了一个算法家族,让这些算法可以互换
模板方法在类层次上运作, 因此它是静态的。 策略在对象层次上运作, 因此允许在运行时切换行为。