模板模式较为简单,就是在抽象类中定义好了相关事件抽象和事件处理流程,子类实现父类的事件抽象,然后执行父类中的事件处理流程即可。
书中的原话也言简意赅:
在父类中定义处理流程的框架,在子类中实现具体处理的模式就称为Template Method模式。–《图解设计模式》
此处我举个蜜雪冰城做饮料的例子,个人认为比书中的更容易理解:
首先,蜜雪冰城总部为门店指定了一套制作饮料的标准流程(步骤之间有严格的顺序):
- 步骤一:店员洗手消毒
- 步骤二:店员取一个空杯子
- 步骤三:店员加入口味糖浆
- 步骤四:店员加入纯净水
- 步骤五:封口
- 步骤六:摇匀
我们使用代码来将这一行为抽象
public abstract class MakeDrinkTemplate {
//洗手抽象函数(抽象事件)
public abstract void washHands();
//拿杯子抽象函数(抽象事件)
public abstract void takeTheCup();
//加入糖浆抽象函数(抽象事件)
public abstract void addSyrup();
//加入纯净水抽象函数(抽象事件)
public abstract void addWater();
//封口抽象函数(抽象事件)
public abstract void seal();
//摇匀抽象函数(抽象事件)
public abstract void shakeWell();
//制作函数,严格指定了流程(事件的处理流程)
public final void makeDrink() {
washHands();
takeTheCup();
addSyrup();
addWater();
seal();
shakeWell();
}
}
以上为公司总部指定的标准流程,当门店需要制作具体的饮品时,就需要按照公司的规定,实现具体的操作流程。
我们将具体的制作方法用代码抽象出来,例如【黄桃果霸】和【冰激凌】的制作流程如下:
//黄桃果霸
public class HuangTaoGuoBa extends MakeDrinkTemplate{
@Override
public void washHands() {
System.out.println("使用洗手液洗手");
}
@Override
public void takeTheCup() {
System.out.println("拿一个饮料杯");
}
@Override
public void addSyrup() {
System.out.println("加入黄桃果霸糖浆");
}
@Override
public void addWater() {
System.out.println("添加纯净水");
}
@Override
public void seal() {
System.out.println("摇匀");
}
@Override
public void shakeWell() {
System.out.println("封口");
}
}
//冰激凌
public class BingJiLing extends MakeDrinkTemplate{
@Override
public void washHands() {
System.out.println("使用洗手液洗手");
}
@Override
public void takeTheCup() {
System.out.println("拿一个冰激凌杯");
}
@Override
public void addSyrup() {
System.out.println("加入冰激凌");
}
@Override
public void addWater() {
System.out.println("不用加水");
}
@Override
public void seal() {
System.out.println("不用封口");
}
@Override
public void shakeWell() {
System.out.println("不用摇匀");
}
}
有了以上具体的饮品制作方法之后,我们再添加一个门店类来控制饮品的制作
public class MenDian {
public static void main(String[] args) {
//制作一个黄桃果霸
HuangTaoGuoBa huangTaoGuoBa = new HuangTaoGuoBa();
huangTaoGuoBa.makeDrink();
System.out.println("|------------------------------------------");
//制作一个冰激凌
BingJiLing bingJiLing = new BingJiLing();
bingJiLing.makeDrink();
}
}
执行后输出:
使用洗手液洗手
拿一个饮料杯
加入黄桃果霸糖浆
添加纯净水
摇匀
封口
|------------------------------------------
使用洗手液洗手
拿一个冰激凌杯
加入冰激凌
不用加水
不用封口
不用摇匀
上面的演示中,我们发现,只要子类实现父类中定义的事件抽象即可,无需关心其具体的事件处理流程(注意:此处的不关心,并不代表不了解,实际情况下,若是子类对父类中的事件处理流程一无所知,是无法正确编写事件实现的)。也可以理解为将子类中相同的事件处理流程提高到父类中,避免子类中重复书写。
并且,当流程发生变化时,只需调整模板即可,例如总部要求流程变为"先拿杯子,后洗手消毒",此时只需要修改模板类即可,而无需修改子类具体实现。