模板方法模式详解:


  • 概念
    模板方法是通过定义一个算法骨架,而将算法中的步骤延迟到子类,这样子类就可以复写这些步骤的实现来实现特定的算法。
  • 使用场景
    1、多个子类有公有的方法,并且逻辑基本相同时。
    2、重复,复杂的算法,可以把核心算法设计为模板方法。
    3、重构时,模板方法模式是一个经常使用的模式。
  • UML结构图分析
    设计模式相关面试问题-模板方法_子类
  • 实际代码分析
    首先建议抽象类:


public abstract class AbstractWork {

//其中声明为final是不允许子类重写
public final void newDay() {
getUp();
goToWork();
work();
getOffWork();
}

//这是每个人都共有的特性
protected void getUp() {
System.out.println("起床啦:");
}

protected abstract void getOffWork();

protected abstract void work();

protected abstract void goToWork();
}


然后具体类来继承它,如下:


/**
* 老板工作
*/
public class BossWork extends AbstractWork {
@Override
protected void getOffWork() {
System.out.println("老板开车去下班");
}

@Override
protected void work() {
System.out.println("老板分配工作给员工");
}

@Override
protected void goToWork() {
System.out.println("老板开车去上班");
}
}



/**
* 普通员工工作
*/
public class StaffWork extends AbstractWork {
@Override
protected void getOffWork() {
System.out.println("员工坐公交去下班");
}

@Override
protected void work() {
System.out.println("员工处理具体工作");
}

@Override
protected void goToWork() {
System.out.println("员工坐公交去上班");
}
}


下面来运用一下:

设计模式相关面试问题-模板方法_ide_02
另外扩展一下:还有一个具体模板,它跟抽象模板定义是不一样的,具体区别如下:
抽象模板 / 具体模板:定义的数量和类型 / 模板方法的数量

模板方法模式在android中的实际运用:


  • activity && fragment
    像咱们的生命周期回调方法就是其父类定义好的,咱们只能去重写,这就是典型的模板方法啦。
  • AsyncTask
    对于它,我们常用的几个方法:onPreExecute()、doInBackground()、onProgressUpdate()、onPostExecute(),其实都是以模板方法定义在AsyncTask当中的,如下:
    设计模式相关面试问题-模板方法_模板方法_03

设计模式相关面试问题-模板方法_ide_04 
而对于AsyncTask的启动通常是要调用它的execute()方法,所以源码定位到它:
设计模式相关面试问题-模板方法_ide_05

 接着来分析一下是怎么在线程池中运行的:
设计模式相关面试问题-模板方法_子类_06

所以这也是为啥AsyncTask只能执行一次的原因啦,好接着继续往下分析:
设计模式相关面试问题-模板方法_ide_07

接着往下执行:
设计模式相关面试问题-模板方法_子类_08

其实这两个变量是在AsyncTask的构造函数中进行初始化的,如下:
设计模式相关面试问题-模板方法_ide_09

而mWorker是WorkerRunnable类型,那WorkerRunnable又是啥类型呢?
设计模式相关面试问题-模板方法_模板方法_10

而它里面就会执行doInBackground()执行异步任务了,如下:
设计模式相关面试问题-模板方法_子类_11

设计模式相关面试问题-模板方法_ide_12

 而mFuture是FutureTask类型,那什么是FutureTask呢?这里需要介绍一下:
1、Future<V>接口:用来获取异步计算结果的,说白了就是对具体的Runnable或者Callable对象任务执行的结果进行获取(get()),取消(cancel()),判断是否完成等操作。
2、FutureTask:FutureTask除了实现了Future接口外还实现了Runnable接口,因此FutureTask也可以直接提交给Executor执行。
明白了FutureTask的作用之后,还是回到mWorker,在执行完doInBackground()之后,还会有如下执行:
设计模式相关面试问题-模板方法_子类_13

继续跟踪:
设计模式相关面试问题-模板方法_模板方法_14

设计模式相关面试问题-模板方法_模板方法_15

而AsyncTask的finish()方法的具体代码如下:
设计模式相关面试问题-模板方法_模板方法_16
所以我们在处理结果就会在onPostExecute()方法里面,至此整个AsyncTask的完整过程就分析完了。