1 模板方法概念
1.1 介绍
模板方法模式是结构最简单的行为型设计模式,也是所有模式中最为常见的几个模式之一,是基于继承的代码复用的基本技术。在其结构中只存在父类与子类之间的继承关系。
1.2 定义
定义一个操作中的算法的架构,而将一些步骤延迟到子类中,使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
1.3 使用场景
(1)多个子类有公有的方法,并且逻辑基本相同。
(2)重要、复杂的算法,可以把核心算法设计为模板方法,周边的相关细节功能由各个子类实现。
(3)重构时,模板方法是一个经常使用的模式,把相同的代码抽取到父类中,然后通过钩子方法约束其行为。
2 模板方法模式UML类图通用
模板方法模式确实非常简单,仅仅使用了Java的继承机制,但它是一个应用非常广泛的模式。
(1)其中,AbsTemplae叫做抽象模板,它的方法分为两类:
- 基本方法,是由子类实现的方法,并且在模板方法被调用。
- 模板方法,可以有一个或几个,一般是一个具体方法,也就是一个框架,实现对基本方法的调度,完成固定的逻辑。
(2)还有一个角色:具体模板。ConcreteClass1和ConcreteClass2属于具体模板,实现父类所定义的一个或多个抽象方法。
(3)注意:为了防止恶意的操作,一般模板方法都加上final关键字,不允许被覆写。
3 模板方法模式简单实现
(1)抽象类
/**
* 抽象类
*/
public abstract class Game {
/**
* 基本方法
*/
abstract void initialize();
abstract void startPlay();
abstract void endPlay();
/**
* 模板方法
*/
public final void play() {
System.out.println("游戏开机");
// 初始化游戏
initialize();
// 开始游戏
startPlay();
// 结束游戏
endPlay();
System.out.println("游戏关机");
}
}
(2)具体实现类
/**
* 具体抽象类
*/
public class LoLGame extends Game{
@Override
void initialize() {
System.out.println("初始化王者荣耀");
}
@Override
void startPlay() {
System.out.println("攻入敌方战场");
}
@Override
void endPlay() {
System.out.println("每打赢,失败,退出游戏");
}
}
(3)客户端
/**
* 客户端
*/
public class Client {
public static void main(String[] args) {
Game game=new LoLGame();
game.play();
}
}
(4)结果
4 Android源码中的模板方法模式
4.1 AsyncTask-Android系统分析之AsyncTask源码解析
在使用AsyncTask时,我们都知道把耗时操作放到doInBackground(Params… params)中,在doInBackground之前,如果想做一些初始化操作,可以把实现写在onPreExecute中,当doInBackground执行完后会执行onPostExecute方法,而我们只需要构建AsyncTask对象,然后执行execute方法。
4.2 Activity的生命周期
另一个比较好的模板方法示例就是Activity的生命周期函数。ActivityThread的main函数被调用后,依次执行Activity的onCreate、onStart、onResume函数,用户通常在Activity的子类中覆写onCreate方法,并且在该方法中调用setContentView来设置布局,这是一个典型的Activity启动流程、也是一个模板方法的应用。
5 与其他模式的区别
(1)工厂方法是模板方法的一种特殊版本。
(2)策略模式和模板方法模式都是封装算法,一个用组合,一个用继承。
(3)策略模式和模板模式通常可以互相替换。它们都像试卷,策略模式是选择题,模板模式是填空题。
6 总结
模板方法模式用4个字概括就是:流程封装。也就是把某个固定的流程封装到一个final方法中,并且让子类能够定制这个流程中的某些或者所有步骤,这就要求父类提取公用的代码,提升代码的复用率,同时带来了更好的可扩展性。
6.1 优点
- 封装不变部分,扩展可变部分。
- 提取公共部分代码,便于维护。
6.2 缺点
需要为每一个基本方法的不同实现提供一个子类,如果父类中可变的基本方法太多,将会导致类的个数增加,系统更加庞大,设计也更加抽象,此时,可结合桥接模式来进行设计。
7 参考文章与链接
《Android源码设计模式解析与实战》
《设计模式之禅》