定义:
定义一个操作中的算法框架,而将一些步骤延迟到子类中,使得子类可以不改变一个算法的结构即可重新定义该算法的某些特定步骤。
模板方法模式类中,有两种方法,一种是基本方法,是由子类实现的,并且在模板方法中调用,这些函数要定义成抽象的;第二种方法时模板方法,实现对基本方法的调度,完成固定的逻辑,这个方法是在父类中就已经实现了的。我们还可以在父类中,定义一个“钩子函数”,用以控制模板方法中,某些基本方法是否执行,这个“钩子函数”可以由子类覆盖,并且在子类中去改变它的返回值,从而控制父类模板方法中某些方法是否执行。具体类图如下:
代码如下:
public abstract class AbstractTemplate {
//基本方法,由子类去实现
protected abstract void doSomething1();
protected abstract void doSomething2();
protected abstract void doSomething3();
//模板方法,为了防止恶意的操作,一般模板方法上都加上final关键字,不允许被覆写
public final void templateMethod(){
doSomething1();
if(this.hook())
doSomething2();
doSomething3();
}
//hook函数,用来控制doSomething2()函数是否执行,默认的是执行的
protected boolean hook(){
return true;
}
}
/**
* doSomething2()总是不执行
*/
public class ConcreteTemplate1 extends AbstractTemplate {
@Override
protected void doSomething1() {
System.out.println("template1 do something 1");
}
@Override
protected void doSomething2() {
System.out.println("template1 do something 2");
}
@Override
protected void doSomething3() {
System.out.println("template1 do something 3");
}
//返回false,表示设置doSomething2()方法总是不执行
protected boolean hook(){
return false;
}
}
/**
* 可以在外部控制doSomething2()方法是否执行
*/
public class ConcreteTemplate2 extends AbstractTemplate {
private boolean isExecute=true;
@Override
protected void doSomething1() {
System.out.println("template2 do something 1");
}
@Override
protected void doSomething2() {
System.out.println("template2 do something 2");
}
@Override
protected void doSomething3() {
System.out.println("template2 do something 3");
}
//覆盖父类的hook()方法
protected boolean hook(){
return this.isExecute;
}
public void setHook(boolean isExecute){
this.isExecute=isExecute;
}
}
/**
* 使用默认的设置,即doSomething2()方法总是执行
*/
public class ConcreteTemplate3 extends AbstractTemplate {
@Override
protected void doSomething1() {
System.out.println("template3 do something 1");
}
@Override
protected void doSomething2() {
System.out.println("template3 do something 2");
}
@Override
protected void doSomething3() {
System.out.println("template3 do something 3");
}
}
场景类:
public class Client {
public static void main(String[] args) {
ConcreteTemplate1 t1=new ConcreteTemplate1();
t1.templateMethod();
ConcreteTemplate2 t2=new ConcreteTemplate2();
t2.setHook(true);//可以在这里设置doSomething2()方法是否执行
t2.templateMethod();
ConcreteTemplate3 t3=new ConcreteTemplate3();
t3.templateMethod();
}
}
模板方法模式的优点:
1、封装不变部分,扩展可变部分
2、提取公共部分的代码,便于维护
3、行为由父类控制,子类实现。基本方法是由子类实现的,因此子类可以通过扩展的方式增加相应的功能,符合开闭原则。