23种设计模式之模板方法模式
模板方法模式的定义
定义一个操作中的算法的框架,而将一些步骤延迟到子类中. 使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤.
通俗的讲,就是将子类相同的方法, 都放到其抽象父类中
类图如下:
其中, AbstractClass 叫抽象模板, 它的方法分为以下两类:
- 基本方法, 基本方法也叫做基本操作, 是由子类实现的方法, 并且在模板方法被调用
- 模板方法, 可以有一个或几个, 一般是一个具体方法, 也就是一个框架, 实现对基本方法的调度, 完成固定逻辑, 一般模板方法都加上final关键字, 不允许被覆写, 以防止恶意的操作
ConcreteClass1和ConcreteClass2叫做具体模板, 实现父类所定义的一个或多个抽象方法, 也就是父类定义的基本方法在子类中得以实现.
抽象模板类实现代码如下:
具体类实现基本方法.
模板方法模式的应用
模板方法模式的优点
- 封装不可变部分,扩展可变部分. 把认为是不变部分的算法封装到父类实现,而可变部分的则可以通过继承来继续扩展
- 提取公共部分代码,便于维护. 试想, 如果我们不抽取到父类,维护人员为了修正一个缺陷,需要到处查找类似的代码
- 行为有父类控制,子类实现. 基本方法是由子类实现的, 因此子类可以通过扩展的方式增加相应的功能, 符合开闭原则
模板方法模式的缺点
按照我们的设计习惯, 抽象类负责声明最抽象,最一般的食物属性和方法, 实现类完成具体的事物属性和方法. 但是模板方法模式却颠倒了, 抽象类定义了部分抽象方法, 由子类实现, 子类执行的结果影响了父类的结果, 也就是子类对父类产生了影响, 这在复杂的项目中,会带来代码阅读的难度, 而且也会让新手产生不适感
模板方法模式的使用场景
- 多个子类有公有的方法,并且逻辑基本相同
- 重要、复杂的算法, 可以把核心算法设计成模板方法, 周边的相关细节功能则由各个子类实现
- 重构时, 模板方法模式是一个经常使用的模式, 把相同的代码抽取到父类中,然后通过钩子函数约束其行为
模板方法模式的扩展
将上面的 AbstractClass 抽象类修改后代码如下:
子类实现 isRun() 方法, 通过子类的不同实现,可以影响到公共代码的执行, 暗爽
也就是说外界条件改变,影响到模板方法的窒息那个. 在我们抽象类中 isRun 的返回值就影响了模板方法的执行结果, 该方法就叫做钩子方法.
模板方法模式就是在模板方法中按照一定的规则和顺序调用基本方法.
使用模板方法模式, 是非常容易扩展的一种模式