一、什么是模板方法模式?
我们经常会遇到一个问题:我们明确了某个方法的执行步骤及其顺序,但是某几个步骤的具体实现我们暂时未知,需要按照具体的情况具体处理。模板方法就是定义了某个方法的执行步骤及顺序,而将某些与具体实现的步骤延迟到子类中去执行。模板方法模式把那些不知道具体实现的步骤封装成抽象的方法,子类通过继承去实现各个抽象。
举个形象的例子,如果我们要画画,那么首先我们规定了画画的步骤:要选择一支画笔,画完后放回去。但是我们并没有规定用蜡笔画呢还是用水彩笔画——这个具体过程由子类去实现。
二、模板方法模式框图
三、模板方法模式的具体实现代码
3.1 AbstractPaint——抽象绘画类
package designpatterns.templateMethod;
/**
* Created by Olive on 2017/12/23.
*/
public abstract class AbstractPaint {
// 模板方法,doPainting需要子类实现,注意到此方法是final的,为什么?
public final void paintingPicture(){
getPen();
doPainting();
putDownPen();
}
public void getPen(){
System.out.println("get pen");
}
public void putDownPen(){
System.out.println("put down pen");
}
protected abstract void doPainting();
}
想一想,为什么paintPicture方法要设定为fianl?
3.2 Crayon——蜡笔类,继承至AbstractPaint
package designpatterns.templateMethod;
/**
* Created by Olive on 2017/12/23.
*/
public class Crayon extends AbstractPaint{
@Override
protected void doPainting() {
System.out.println("Crayon");
}
}
3.3 WatercolorPen——水彩笔类,继承至AbstractPaint
package designpatterns.templateMethod;
/**
* Created by Olive on 2017/12/23.
*/
public class WatercolorPen extends AbstractPaint{
@Override
protected void doPainting() {
System.out.println("Watercolor Pen");
}
}
3.4 Client——客户端
package designpatterns.templateMethod;
/**
* Created by Olive on 2017/12/23.
*/
public class Client {
public static void main(String[] args){
AbstractPaint pen1 = new Crayon();
pen1.paintingPicture();
System.out.println("************************************");
AbstractPaint pen2 = new WatercolorPen();
pen2.paintingPicture();
}
}
3.5 结果
get pen
Crayon
put down pen
************************************
get pen
Watercolor Pen
put down pen
Process finished with exit code 0
四、一点小总结
在实际中,有很多地方会用到模板方法模式,比如jdk中Collections类的sort方法就是一个模板方法,它将其中的比较器Comparator交给具体对象去实现。但是模板方法也有一定的设计缺陷,首先模板方法模式是通过继承得到的,这在一定程度上使父类与子类间紧耦合;另外,从面向对象这个角度来说,一般父类负责抽象,子类负责具体实现。但是在模板方法模式中,父类规定了方法的具体步骤,只将一部分抽象实现交给了子类,同时也增加了子类实现的负担。
另外注意到,一般来说应用模板方法模式时,父类规定的模板方法的执行顺序是不能修改的,子类只能修改覆盖抽象的那部分,所以可以看到我们上面的paintingPicture方法是final的 ,也就是说不能被子类继承及修改。