模板模式的定义:在一个方法中定义一个算法的框架,而将一些步骤延迟到子类中。模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。这个地方用到的设计原则是好莱坞原则,等我调用你,不用你来调用我。防止“依赖腐败”
书中讲解的例子是Beverage的例子,之前我们在装饰者模式中讲到了Beverage的例子,装饰者模式是添加了一些责任,让我们的cost方法变得间接。这次我们看Beverage的例子讲的是饮料制作步骤的例子
class Tea extends Wrapper{
void prepareBeverage(){
boilWater()//烧水
steepTeaBag()//泡茶包
pourIncup()//倒入被子
addLemon()//添加柠檬
}
}
class Coffee extends Wrapper{
void prepareBeverage{
boilWater()//烧水
brewCoffeeGrinds()//冲咖啡粉
pourIncup()//倒入被子
addSugerAndMilk()//添加牛奶和糖
}
}
我们看到制作Tea和制作Coffee的过程,都有boilWater和 pourInCup方法,而且泡茶包和冲咖啡的动作也很相似,最后添加辅料的方法其实意义是一样的,只是添加的对象不一样,动作是一样的,那我们就可以把制作的过程抽象出来,规范化我们的制作步骤,让所有的热饮都遵循这个步骤
抽象的步骤是在父类中定义一组算法,
abstract class Wrapper{//这个Wrapper是装饰者的wrapper,有兴趣大家可以翻看前面的文章
abstract void prepareBeverage(){
boilWater();
brew();//冲泡
pourInCup();
addCondiments();//添加辅料
}
void boilWater(){
syso("烧水");
}
void pourInCup(){
syso("倒入被子");
}
abstract void brew();//冲泡
abstract void addCondiments();//添加辅料
}
我们看到抽象类 Wrapper的制作饮料的方法是抽象的,里面用到的四个步骤,brew()和addCondiments()方法都是抽象的,因为具体的实现不一样,所以我们让子类自己实现。而boilWater()和pourInCup()是一样的,我们就把实现放在父类里面,统一行为。
模板方法看样子很死板,定义了算法都要按步执行,但是我们可以写hook(钩子)来定制执行步骤,比如客户不想加糖和奶,喜欢苦咖啡,我们可以在Wrapper的prepareBeverage() 方法中,定义boolean hook()方法,在coffee的addCondiments()方法实现中判断 if(hook()){}else{}来差异化是否添加辅料
其实jdk中有很多模板方法,书中讲的是 Arrays.sort()和jframe.paint()方法,JFrame.paint()方法是钩子方法,
我们实际项目中也可以定义模板方法模式,当我们发送信息的时候,分为短信,db消息,push消息等,虽然发送途径不一样,但是数据准备,校验都是一样的,那我们可以用模板方法规范我们的算法步骤。