1 定义
模板模式,全称模板方法设计模式,Template Method Design Pattern。
GoF《设计模式》的定义: Define the skeleton of analgorithm in an operation, deferring some steps to subclasses. Template Method lets subclasses redefine certain steps of an algorithm without changing the algorithm’s structure.
模板方法模式在一个方法中定义一个算法骨架,并将某些步骤推迟到子类中实现。模板方法模式可以让子类在不改变算法整体结构的情况下,重新定义算法中的某些步骤。
算法骨架就是“模板”
包含算法骨架的方法就是模板方法
所以叫模板方法模式,属行为型模式。
一个抽象类公开定义了执行它的方法的方式/模板。它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行。
2 原理
- 模板方法模式的通用类图
- 仅利用了Java的继承机制,AbstractClass是抽象模板,其方法分为两类:
基本方法
基本操作,定义为abstract,强制子类实现,并在模板方法被调用
模板方法
一般是一个具体方法,即一个框架,实现对基本方法的调度,完成固定逻辑
模板方法加上final关键字,不允许被重写。
在类图中还有一个角色:具体模板。ConcreteClass1和ConcreteClass2属于具体模板,实现父类所定义的一个或多个抽象方法,即父类定义的基本方法在子类中得以实现。
抽象模板类
public abstract class AbstractClass { // 基本方法 protected abstract void doSomething(); // 基本方法 protected abstract void doAnything(); // 模板方法 public void templateMethod() { /* * 调用基本方法,完成相关的逻辑 */ this.doAnything(); this.doSomething(); } }
具体模板类
public class ConcreteClass1 extends AbstractClass { // 实现基本方法 protected void doAnything() { // 业务逻辑 } protected void doSomething() { // 业务逻辑处理 } } public class ConcreteClass2 extends AbstractClass { // 实现基本方法 protected void doAnything() { // 业务逻辑处理 } protected void doSomething() { // 业务逻辑处理 } }
场景类
public class Client { public static void main(String[] args) { AbstractClass class1 = new ConcreteClass1(); AbstractClass class2 = new ConcreteClass2(); //调用模板方法 class1.templateMethod(); class2.templateMethod(); } }
抽象模板中的基本方法尽量设计为protected类型,符合迪米特法则,不需要暴露的属性或方法尽量不要设置为protected类型。实现类若非必要,尽量不要扩大父类中的访问权限。
Spring 中对 Hibernate 的支持,将一些已经定好的方法封装起来,比如开启事务、获取 Session、关闭 Session 等,程序员不重复写那些已规范好的代码,直接丢一个实体即可保存。
3 使用场景
- 多个子类有公有的方法,并且逻辑基本相同时
- 重要、复杂的算法,可将不变的核心算法设计为模板方法,周边的相关细节功能、可变的行为由各个子类实现
重构时,模板方法模式是一个经常使用的模式,把相同代码抽取到父类,然后通过钩子函数约束其行为
4 案例
创建一个定义操作的 Game 抽象类,其中,模板方法设置为 final,这样它就不会被重写。