何为模板方法模式
模板方法模式在一个方法中定义一个算法的骨架,而把一些步骤延迟到子类。模板方法使得子类在不改变算法结构的情况下,重新定义算法中的某些步骤。
模板方法模式属于行为型模式,其对应的类图如下所示。
图片来源于 HeadFirst 设计模式。
举例
提到模板方法模式,我想到了炒菜。炒菜主要的步骤如下:
倒油 -> 烧油 -> 炒蒜 -> 炒菜 -> 放盐 -> 加水 -> 出锅
我们现在可以用代码来模拟炒菜,其中以上的步骤是炒菜的通用步骤,也就是说以上几步是炒菜的共性,可以将其抽取出来。抽取后的代码如下所示。
public abstract class Dish {
/**
* 炒菜步骤不能随意破坏
*/
public final void prepareDish() {
pourOil();
boilOil();
fry();
addSalt();
addWater();
beforeServed();
served();
afterServed();
}
protected void pourOil() {
System.out.println("倒入适量的油...");
}
protected void boilOil() {
System.out.println("开始烧油...");
}
// 炒的内容由不同的菜决定
protected abstract void fry();
protected void addSalt() {
System.out.println("加半勺盐...");
}
protected void addWater() {
System.out.println("加50ml水...");
}
protected void served() {
System.out.println("出锅,装碗...");
}
// 出锅之前需要做什么?(默认不做)
protected void beforeServed() {
}
// 出锅之后需要做什么?(默认不做)
protected void afterServed() {
}
}
接下来就是毛豆炒肉了,毛豆炒肉的炒法,不过毛豆炒肉的做法比较简单。
public class EdamameStirFry extends Dish {
@Override
protected void fry() {
System.out.println("倒入蒜子和青椒炒20秒...");
System.out.println("倒肉,炒肉至炒熟...");
System.out.println("倒入毛豆,翻炒1分钟...");
}
@Override
protected void beforeServed() {
System.out.println("加20ml生抽...");
}
}
不过有些菜在炒的时候不需要加水,炒完即可直接出锅。比如韭菜炒蛋,韭菜在炒的时候水分就容易流出来,所以不需要加水,说起韭菜炒蛋,要先单独炒蛋,再炒韭菜,但是有些菜确实有这种分开炒的步骤,所以我们需要将抽象类中的步骤修改一下。甚至有些菜还需要焯水的步骤等等(比如西兰花)。
public abstract class Dish {
protected int times = 0; // 提前出锅次数
/**
* 炒菜步骤不能随意破坏
*/
public final void prepareDish() {
if(isBoilingWater()) {
boilingWater();
}
pourOil();
boilOil();
fry();
// 当要提前出锅备用时,我们可以用钩子函数
while(isAdvance()) {
times++;
served();
pourOil();
boilOil();
fry();
}
addSalt();
addWater();
beforeServed();
served();
afterServed();
}
// 是否需要提前出锅的操作
protected boolean isAdvance() {
return false;
}
// 炒菜之前是否要焯水
protected boolean isBoilingWater() {
return false;
}
// 焯水
protected void boilingWater() {
}
// 其他方法省略
}
韭菜炒蛋的步骤
public class EggsWithLeek extends Dish {
@Override
protected void fry() {
if (times == 0) {
System.out.println("倒入鸡蛋液...");
System.out.println("开始翻炒30秒...");
return;
}
if(times == 1) {
System.out.println("倒入韭菜...");
System.out.println("开始炒韭菜...");
super.addSalt();
System.out.println("倒入炒好的鸡蛋...");
}
}
@Override
protected void addWater() {
}
@Override
protected void addSalt() {
}
@Override
protected boolean isAdvance() {
return times < 1;
}
}
运行一下
public class TemplateTest {
public static void main(String[] args) {
System.out.println("毛豆炒肉-------------");
EdamameStirFry edamameStirFry = new EdamameStirFry();
edamameStirFry.prepareDish();
System.out.println("韭菜炒蛋-------------");
EggsWithLeek eggsWithLeek = new EggsWithLeek();
eggsWithLeek.prepareDish();
}
}
运行结果如下:
毛豆炒肉-------------
倒入适量的油...
开始烧油...
倒入蒜子和青椒炒20秒...
倒肉,炒肉至炒熟...
倒入毛豆,翻炒1分钟...
加半勺盐...
加50ml水...
加20ml生抽...
出锅,装碗...
韭菜炒蛋-------------
倒入适量的油...
开始烧油...
倒入鸡蛋液...
开始翻炒30秒...
出锅,装碗...
倒入适量的油...
开始烧油...
倒入韭菜...
开始炒韭菜...
加半勺盐...
倒入炒好的鸡蛋...
出锅,装碗...
Java 中的模板方法模式
- sort() 方法,给对象进行排序时,排序的算法已经写好,但是排序时的两个对象的比较是不知道的,需要实现 Comparable 接口中的 compareTo() 方法来决定两个对象的大小。
- jdbcTemplate
请勿发布违反中国大陆地区法律的言论,请勿人身攻击、谩骂、侮辱和煽动式的语言。