定义:在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中。
模板方法模式使得子类可以在不改变算法结构的前提下,重新定义算法中的某些步骤的实现。
我们都知道Activity的7个生命周期方法,这个流程是死的,可是这个是怎么来的呢?
就是用的模板方法模式。
定义看起来非常难懂,我通俗的理解是这样的:
对于实现步骤相同的事务来讲,我们可以把这些步骤抽象出来,定义成一个具体的框架,或者说是一个具体的流程。
这里我用了Head First上的例子,冲泡茶和咖啡,都需要四个步骤:
1.把水煮沸
2.冲泡(茶/咖啡)
3.倒进杯子
4.加额外的调料(牛奶/糖)
即泡茶和冲咖啡的流程就是这个流程,不管你冲的是什么咖啡,泡的是什么茶,但是步骤是死的。
那么就可以定义一个类,将这些个步骤封装起来,然后需要泡咖啡或者是泡茶的时候就继承这个类就好了。
但是还有一点,步骤2和步骤4在具体实现的时候可能是不一样的,制作茶的时候冲的是茶,加的可能是糖,而咖啡可能还要加牛奶。
既然已经有了继承关系,那么只需要将这两个方法在子类中重写即可,而对于步骤1和步骤3,不希望子类改变,可以将其直接写死,不让子类重写。
另外,这个步骤是死的,不能被改变的,因此也需要写死。
可是,还有一个问题,我要是泡茶的时候不想加额外的东西,我就想第三步就可以直接喝了,这样的话这个步骤是死的,岂不是做不到了。
所以,为了保证灵活起见,可以在上面的步骤中增加一些判断,看是否需要第四步,不需要的话就不执行,实现起来就是在模板中增加一个判断,这个判断的方法由抽象类提供默认实现,子类也可以拥有自己的实现,自己选择是否需要执行这个步骤,这样一来就很灵活了。(这就是钩子)
代码:
首先是模板类
public abstract class Drinks {
public final void makeDriks(){
boliWater();
brew();
pourInCup();
if(needCondiments()){
addCondiments();
}
}
private void boliWater() {
System.out.println("把水煮沸...");
}
protected abstract void brew();
private void pourInCup() {
System.out.println("倒进杯子...");
}
public boolean needCondiments(){
return true;
}
protected abstract void addCondiments();
}
然后是咖啡实现:
public class Coffee extends Drinks {
@Override
protected void brew() {
System.out.println("冲泡咖啡...");
}
@Override
protected void addCondiments() {
System.out.println("向咖啡里加牛奶...");
}
}
然后是茶的实现:
public class Tea extends Drinks {
@Override
protected void brew() {
System.out.println("冲泡茶...");
}
@Override
protected void addCondiments() {
System.out.println("向茶里加糖...");
}
@Override
public boolean needCondiments() {
return false;
}
}
最后测试:
public class Test {
public static void main(String[] args) {
Coffee coffee = new Coffee();
coffee.makeDriks();
System.out.println("\n");
Tea tea = new Tea();
tea.makeDriks();
}
}
简单的说,就是定义一个模板类,其中定义一个方法,内部有一系列调用其他方法的逻辑,其中的一些自己默认实现,一些提供给子类来进行个性化实现。子类继承了这个类之后,默认的就拥有了这一系列的处理逻辑,加上自己的实现,就能够在模板的基础上构造出一个新的事物。