简介
模板方法模式(Template Method Pattern)又叫模板模式,是指定义一个操作中的算法的框架,而将一些步骤延迟到子类中。使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤,属于行为型设计模式。
模板方法模式实际上是封装了一个固定流程,该流程由几个步骤组成,具体步骤可以由子类进行不同实现,从而让固定的流程产生不同的结果。
模板方法模式UML类图:

从UML类图中,我们可以看到,模板方法模式主要包含两种角色:
抽象模板(AbstractClass):抽象模板类没定义了一套算法框架/流程。
具体实现(ConcreteClass):具体实现类,对算法框架/流程的某些步骤进行了实现。
模板方法模式中的钩子方法
public abstract class AbstractClass {
public final void step() {
step1();
step2();
step3();
if (needCheckHomeWork()) {
checkHomeWork();
}
}
public void step1() {
System.out.println("step1");
}
public void step2() {
System.out.println("step2");
}
public void step3() {
System.out.println("step3");
}
public abstract void checkHomeWork();
public Boolean needCheckHomeWork() {
return false;
}
}
设计钩子方法的主要目的是用来干预执行流程,使得我们控制行为流程更加灵活,更符合实际业务的需求。钩子方法的返回值一般为适合条件分支语句的返回值。
模板方法模式在源码中的使用
1、JDK中的AbstractList
-
public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E> { ... abstract public E get(int index); ... }
-
HttpServlet 里面的
service()
、doGet()
、doPost()
2、Mybatis中BaseExecutor类
public abstract class BaseExecutor implements Executor {
...
protected abstract int doUpdate(MappedStatement ms, Object parameter) throws SQLException;
protected abstract List<BatchResult> doFlushStatements(boolean isRollback) throws SQLException;
protected abstract <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException;
protected abstract <E> Cursor<E> doQueryCursor(MappedStatement ms, Object parameter, RowBounds rowBounds, BoundSql boundSql)
throws SQLException;
...
}
实现BaseExecutor的子类图

模板方法模式的优缺点
优点:
1、利用模板方法将相同处理逻辑的代码放到抽象父类中。可以提高代码的复用性。
2、将不同的代码不同的子类中,通过对子类的扩展增加新的行为,提高代码的扩展性。
3、把不变的行为写在父类上,去除子类的重复代码,提供一个很好的代码复用平台,符合开闭原则。
缺点:
1、类数目的增加,每一个抽象类都需要一个子类来实现,这样导致类的个数增加。
2、类数量的增加,间接的增加了系统实现的复杂度。
3、继承关系自身缺点,如果父类增加新的抽象方法,所有的子类都要修改一遍。