说明
模板方法模式是行为型设计模式中的一种,在开发中使用的频率相对还是比较高的,主要用来定义一些逻辑的执行流程,也就是算法的骨架。同时呢,模板方法也是相对比较简单的一种设计模式,其涉及的结构,相关的类相较其它的模式来说,比较的少。一般的,只会涉及父类子类这一种关系,父类负责定义算法的骨架,而具体的实现由子类去完成。
模板方法UML图
从图中我们可以看出,模板方法主要由两部分组成:
- 抽象模板类: 主要定义算法的结构,也就是业务逻辑的执行流程。这里模板方法里的流程可分为固定的和非固定的两部分,如果是固定的就由抽象类自己去实现,而将非固定的,让子类去实现具体的方法。一般,模板的方法需要使用
final
来进行修辞,意思是,不能让子类去修改父类模板方法的所定义的业务逻辑。- 具体模板类: 主要是根据具体的类型去实现相应逻辑。子类可以有很多个,每个具体模板类的具体方法实现是不一样的。
模板方法的简单例子
比如,我们手机里通过会下载一些游戏,比如:王者荣耀,魂斗罗…当我们要玩具体某一个游戏的时候,固定的步骤是先打开游戏,然后开始玩游戏,当不想玩的时候,我们会退出游戏,实现上,这就是一个典型的模板方法设计模式的体现。我们下面使用代码的方式来对其进行实现。
抽象模板类
public abstract class AbstractMethodClass {
/**
* 定义算法的执行流程
*/
protected final void templateMethod() {
openGame();
playGame();
exitGame();
}
protected abstract void exitGame();
protected abstract void playGame();
protected abstract void openGame();
}
通过templateMethod()
方法定义了三个抽象方法,分别是打开游戏,玩游戏和退出游戏。而具体打开哪个游戏,怎么玩以及退出哪个游戏我们是不清楚的,只有在玩具体的游戏的时候才能确定。
具体模板类
public class KingGame extends PlayGameClass {
@Override
protected void exitGame() {
System.out.println("退出王者荣耀");
}
@Override
protected void playGame() {
System.out.println("和兄弟们正在发起对敌人的进攻");
}
@Override
protected void openGame() {
System.out.println("打开王者荣耀");
}
}
魂半罗类和此类是类似的代码,就不贴了,这里分别针对不同的游戏来做出了相应的实现。
模板方法的扩展
当在使用模板方法的时候,根据实际情况,我们可以在抽象类中,给相应的方法以默认的实现,可以是空实现或者是一个默认的实现。如果子类 有特殊的需求,可以通过覆盖相对应的方法来更改其实现。 比如:我们在写ListView
的adapter
时,如果继承自BaseAdapter
时,其中的getItemViewType
和getViewTypeCount
都是有默认的实现,而如果我们需要在listView
中使用多种类型的item
的话,就需要覆写这两个方法,来替换父类中的默认实现。
总结
优点
- 容易扩展。只需实现相应的抽象方法,就可以针对具体的情况很容易实现功能的扩展。
- 便于维护。模板方法统一了业务流程,如果需要对业务流程进行修改,只需要维护模板方法一处地方,而普通的实现,业务逻辑都散落在各个类中,修改起来就比较麻烦。
缺点
- 每一个不同的实现都需要新建一个类,会导致类个数的膨胀。
适用场景
- 需要统一算法的执行流程时。
- 需要对各子类中的行为进行抽象,以避免代码重复时。
- 需要控制子类的扩展时。