该文章是本人在慕课学习模板模式是做的一些笔记
模板方法模式
定义了一个操作算法框架,而将一些步骤延迟到子类中实现,
使得子类在不改变一个算法结构的同时就重新定义该算法的某些特定步骤。
案例介绍:
煮咖啡、泡茶都有相同的一些步骤,也有一些独有的步骤
1、煮水
2、泡
3、倒进杯子
4.加调料
demo:
package Template;
/*
* 模版模式
* 抽象基类,为所有子类提供一个算法框架。提神饮料
*/
public abstract class RefreshBeverage {
//需要使用final关键字,避免被修改
public final void prepareBeverageTemplate(){
boilWater();
brew();
pourInCup();
addCondiments();
}
protected abstract void addCondiments();
protected abstract void brew ();
private void pourInCup() {
System.out.println("倒进杯子");
}
private void boilWater() {
System.out.println("煮水");
}
}
package Template;
public class coffee extends RefreshBeverage {
@Override
protected void addCondiments() {
System.out.println("加奶加糖");
}
@Override
protected void brew() {
System.out.println("使用沸水冲coffee");
}
}
package Template;
public class tea extends RefreshBeverage {
@Override
protected void addCondiments() {
System.out.println("加柠檬水");
}
@Override
protected void brew() {
System.out.println("使用70度的开水泡茶");
}
}
测试:
package Template;
public class test {
public static void main(String[] args) {
coffee cof= new coffee();
System.out.println("coffee开始");
cof.prepareBeverageTemplate();
System.out.println("coffee结束");
System.out.println("开始泡茶");
tea tea = new tea();
tea.prepareBeverageTemplate();
System.out.println("结束泡茶");
}
}
测试结果:
package Template;
public class tea extends RefreshBeverage {
@Override
protected void addCondiments() {
System.out.println("加柠檬水");
}
@Override
protected void brew() {
System.out.println("使用70度的开水泡茶");
}
}
以上就是简单的模板模式的基本步骤
引出一个问题就是,如果提供给子类的实现的方法如blew()与addCondiments()这些,子类不想实现又该如何解决。
引出了钩子方法进行个性化扩展
// 需要使用final关键字,避免被修改
public final void prepareBeverageTemplate() {
boilWater();
brew();
pourInCup();
if (isNeedCondiments()) {
addCondiments();
}
}
protected boolean isNeedCondiments() {
// 默认是要加调料
return true;
}
子类tea.java进行添加
// 子类通过覆盖的形式选择挂载的钩子函数
@Override
protected boolean isNeedCondiments() {
// 不要加料
return false;
}
这样就可以使得加料的钩子函数不会执行
再次运行结果为:
coffee开始
煮水
使用沸水冲coffee
倒进杯子
加奶加糖
coffee结束
开始泡茶
煮水
使用70度的开水泡茶
倒进杯子
结束泡茶
上述就是钩子函数的用法。
下面是一些理论的知识(来自慕课笔记)
模版方法模式的实现要素分析
抽象基类
1.基本方法:对各种具体子类而言是相同,具有共性的步骤
2.抽象方法:只知道具体原则,而不知道实现细节,需要延迟到子类实现的步骤
3.钩子方法:在基类中提供一个默认或空的实现,子类可以挂载及覆盖实现
4.模版方法:Template方法(final),将基本方法、抽象方法、钩子方法按照业务逻辑的需求,
汇总而成一个模版方法。一定要声明为final,以防止被子类覆写。
具体子类
1.实现基类中的抽象方法:以提供个性化的、具体的、独特的实现
2.覆盖钩子方法:更加个性化的影响模版方法局部的行为
模版方法模式的实现要素
准备一个抽象类,将部分逻辑以具体方法的形式实现,
然后声明一些抽象方法交由子类实现剩余逻辑,
用钩子方法给予子类更大的灵活性。
最后将方法汇总构成一个不可改变的模版方法。
模版方法模式的适用场景
1.算法或操作遵循相似的逻辑
2.重构时(把相同的代码抽取到父类中)
3.重要、复杂的算法,核心算法设计为模版算法
模版方法模式的优点
封装性好:封装了一个算法的框架,将算法的具体步骤封装成一个通用的模版方法
复用性好:抽取共性的方式,大部分代码在父类实现,个性化逻辑由子类实现
屏蔽细节:很多共性作为私有方法在抽象基类中实现,对子类屏蔽了很多细节
便于维护:好的复用性可以减少代码框架的设计,支持更加灵活的业务变更
模版方法模式的缺点
每一个不同的实现都需要一个子类来实现,导致类的个数增加,使得系统更加庞大。
java单继承,就不能继承多个抽象基类了。