模板模式- 2020-12-04 23:00- 设计模式:
在模板模式(Template Pattern)中,一个抽象类公开定义了执行它的方法的方式/模板。它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行。这种类型的设计模式属于行为型模式。
定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
适用场景
1、一次性实现一个算法的不变的部分,并将可变的行为留给 子类来实现。
2、各子类中公共的行为被提取出来并集中到一个公共的父类 中,从而避免代码重复。
优点
1、提高代码的复用性。
2、提高代码的扩展性。
3、符合开闭原则。
缺点
1、类数目的增加。
2、间接地增加了系统实现的复杂度。
3、继承关系自身缺点,如果父类添加新的抽象方法,所有子 类都要改一遍。
demo
/**
* 做饭
*模板类:定义好一系列步骤
* @author Bai
* @date 2020/12/4 23:29
*/
public abstract class Cooking {
/**
* 做饭
*/
public void cooking() {
//准备食材
prepareIngredients();
//烹饪
cook();
//出锅
readToEat();
}
protected abstract void readToEat();
protected abstract void cook();
protected abstract void prepareIngredients();
}
/**
* 蛋炒饭
*
* @author Bai
* @date 2020/12/4 23:39
*/
public class EggFriedRice extends Cooking {
@Override
protected void readToEat() {
System.out.println("一盘蛋炒饭出锅,开吃。。。");
}
@Override
protected void cook() {
System.out.println("翻炒蛋炒饭。。。");
}
@Override
protected void prepareIngredients() {
System.out.println("准备鸡蛋和米饭");
}
}
/**
* 小炒肉
*
* @author Bai
* @date 2020/12/4 23:41
*/
public class FriedPorkWithChili extends Cooking {
@Override
protected void readToEat() {
System.out.println("装盘配蛋炒饭吃。。");
}
@Override
protected void cook() {
System.out.println("爆炒辣椒和肉。。");
}
@Override
protected void prepareIngredients() {
System.out.println("准备辣椒和猪肉。。");
}
}
源码分析
JDK中的AbstractList
先来看 JDK 中的 AbstractList,代码:
package java.util;
public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E> {
...
abstract public E get(int index);
...
}
我们看到 get()是一个抽象方法,那么它的逻辑就是交给子类来实现,我们大家所熟知的 ArrayList 就 是 AbstractList 的 子 类 。 同 理 , 有 AbstractList 就 有 AbstractSet 和 AbstractMap。
HttpServlet
HttpServlet,有三个方法 service()和 doGet()、doPost()方法,都是模板方法的抽象实现
MyBatis中的BaseExecutor
BaseExecutor 类,它是一个基础的SQL 执行类,实现了大部分的 SQL 执行逻辑,然后把几个方法交给子类定制化完成,源码如下:
public abstract class BaseExecutor implements Executor {
...
protected abstract int doUpdate(MappedStatement var1, Object var2) throws SQLException;
protected abstract List<BatchResult> doFlushStatements(boolean var1) throws SQLException;
protected abstract <E> List<E> doQuery(MappedStatement var1, Object var2, RowBounds var3, ResultHandler var4, BoundSql var5) throws SQLException;
protected abstract <E> Cursor<E> doQueryCursor(MappedStatement var1, Object var2, RowBounds var3, BoundSql var4) throws SQLException;
...
}
如doUpdate、doFlushStatements、doQuery、doQueryCursor 这几个方法就是交 由子类来实现
参考资料:https://www.runoob.com/design-pattern/template-pattern.html
**