定义:用来定义一个操作中的算法框架,而将一些步骤延迟到子类中。使得子类可以不改变一个算法的结构即可重新定义该算法的某些特定步骤。
在一个软件开发的过程中,如果相同的一段代码,复制过两次,就需要对设计产生怀疑。面向对象要求我们,用抽象来解决子类共性的封装。
模板方法,有两种方法,一种是基本方法,另一种是模板方法。下面来看一个基本模板。
抽象模板类
public abstract class AbstractClass {
//基本方法
protected abstract void doSomeThing();
//基本方法
protected abstract void doAnyThing();
//模板方法
public void templeteMethod(){
/*
* 调用基本方法
* */
doSomeThing();
doAnyThing();
}
}
具体模板类
public class ConcreteClass1 extends AbstractClass {
@Override
protected void doSomeThing() {
System.out.println("do 1");
}
@Override
protected void doAnyThing() {
System.out.println("do 2");
}
}
public class ConcreteClass2 extends AbstractClass {
@Override
protected void doSomeThing() {
System.out.println("do 1");
}
@Override
protected void doAnyThing() {
System.out.println("do 2");
}
}
场景类
public class Client {
public static void main(String[] args) {
AbstractClass concreteClass1 = new ConcreteClass1();
AbstractClass concreteClass2 = new ConcreteClass2();
//调用模板方法
concreteClass1.templeteMethod();
concreteClass2.templeteMethod();
}
}
这是模板方法的基本实现,但这样还是不完美,还有一个重要的点还没有涉及到,那就是钩子方法。
我们来想像一下这样一个场景,当我们需要通过实现类对模板方法产生一个约束的时候,我们需要怎么办到。这个时候急用到了钩子方法。
我们只要修改一下模板类,和要控制的实现类即可,具体看代码。
模板类修改
public abstract class AbstractClass {
//基本方法
protected abstract void doSomeThing();
//基本方法
protected abstract void doAnyThing();
//模板方法
public void templeteMethod(){
/*
* 调用基本方法
* */
doSomeThing();
if (isUse()) doAnyThing();
}
protected boolean isUse(){
return true;
}
}
实现类修改
public class ConcreteClass1 extends AbstractClass {
private boolean isUse = true;
@Override
protected void doSomeThing() {
System.out.println("do 1");
}
@Override
protected void doAnyThing() {
System.out.println("do 2");
}
public void setIsUse(boolean ok){
isUse = ok;
}
@Override
protected boolean isUse() {
return isUse;
}
}
其中isUse就是所谓的钩子方法。这个方法才是模板方法最优美的实现。