Demo 地址: https://github.com/ooblee/HelloDesignPattern
1. 定义
模板方法模式:定义一个操作中算法的框架,而将一些步骤延迟到子类中。模板方法模式使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
抽象通用的部分,把变化的开放出来。通过继承的方式,交给子类自己去实现。而所有复杂的流程、算法等等,对子类透明,一方面做到了代码复用,另一方面又保持了对修改关闭、对扩展开放的原则。有新的变化,继承抽象类,然后去实现模板方法
现实生活中的模型
我们要做红烧肉,假设我们抽象出它的基本流程,制定了这样一个模板
加入焯肉 -> 翻炒 -> 加入配料卤煮 -> 收汁
然后在加入配料卤煮这一个地方,因为各个地方的产物不同或者口味不同,发生了很多变化
比如,加冰糖,带甜味的
比如,加辣椒,带辣味的
比如,加陈皮,带酸甜味的
…
这时候,我们的红烧肉模板有个变化的地方,就是配料。这个就可以抽象成一个模板方法模式,通用部分在抽象类中,而变化的地方在子类中实现。这样,各地拿到了红烧肉的制作模板,就可以改变配料实现自己的口味了
2. 设计
主要角色:
- 抽象类,把一个算法的公用部分做成模板。
- 流程上,封装了整个创建、处理、生命周期、销毁等等基本操作。
- 结构上,封装了使用的各个部件的连接、依赖。
- 然后把变化的点,定义一个钩子方法,交给子类去实现。
- 具体子类,覆盖父类的钩子方法。
比如这样的结构
即把通用稳定的部分,做成模板放在抽象类中,然后把变化的部分做成钩子方法给具体实现类实现
3. 应用
可以应用在这些场景:
- 抽象公共代码。有多个子类,有很多的公共行为,把这些代码提取到共同父类,避免代码重复。
- 封装算法。在父类中构建整个算法的步骤、结构,然后把变化的点通过钩子方法,交给子类实现。
- 和策略模式配合。如果策略模式下,多个算法的变化小,可以用模板方法进行优化。
- 反向控制。可以钩子方法,让子类来控制父类的业务逻辑。
4. 特点
4.1. 优点
- 延迟实现,一些细节的处理可以延迟到子类实现。
- 代码复用,通过继承的方式来进行复用。
- 反向控制。
- 易扩展,不同子类可以提供不同的实现,不需要修改模板类。
4.2. 缺点
- 类膨胀,如果变化点过多的情况下,会导致子类的个数增加。如果是多维度的情况,可以应用桥接模式进行优化。
4.3. 对比策略模式
看到模板方法的描述,会觉得和策略模式有些像。这里做一个简单的区别。
要达到的效果不一样:
- 模板方法:抽象出一个算法的通用部分,形成一个稳定的框架,然后对某些变化的点延迟到子类去处理,又称为 Hook 过程。
- 策略模式:把一系列算法封装成一个个独立的类,相互可替换。
变化的粒度不一样:
- 模板方法:模板方法已经把一个完成的算法的具体步骤抽象出一个框架,或者成为模板,然后再把一些变化的点交给子类去实现,变化的粒度小,子类要做的事情也少。
- 策略模式:每个子类都会实现一套完整的算法
这两个可以设计模式可以配合使用。