一.模板模式
1. 模板方法模式初探
模板操作模式定义了一个算法中的统一框架,而将一些步骤延迟到子类中实现,使得子类可以在不改变算法结构的同时重新定义算法的某些特定步骤。这就是模板模式。
1. 模板方法模式的代码实现
1.1 用抽象基类定义框架
/*
* 抽象基类,为所有子类提供一个算法框架
* 提神饮料
*/
public abstract class RefreshBeverage {
//禁止子类对算法框架做任何的改变.Template模板
/*
* 制备饮料的模板方法
* 封装了所有子类共同遵循的算法框架
* ctrl+1 可以自动生成方法
*/
public final void prepareBeverageTemplate() {
//1.将水煮沸
boilWater();
//2.泡制饮料
brew();
//3.将饮料倒入杯中
pureInCup();
//4.加入调味料
addCondiments();
}
/*
* 抽象的基本方法,加调料
*/
protected abstract void addCondiments();
/*
* 抽象的基本方法,泡制饮料
*/
protected abstract void brew() ;
private void pureInCup() {
// TODO Auto-generated method stub
System.out.println("将饮料倒入杯中");
}
/*
* 基本方法,将水煮沸。向下屏蔽细节
* 对所有子类而言是一个共同的行为,不必向子类做过多地开放。故用private进行修饰
*/
private void boilWater() {
// TODO Auto-generated method stub
System.out.println("将水煮沸");
}
}
2.2 具体子类实现延迟步骤
/*
* 具体子类,提供了咖啡制作的基本实现
*/
public class Coffee extends RefreshBeverage {
@Override
protected void brew() {
// TODO Auto-generated method stub
System.out.println("用沸水冲泡咖啡");
}
@Override
protected void addCondiments() {
// TODO Auto-generated method stub
System.out.println("加入糖和牛奶");
}
}
/*
* 具体子类,提供了茶制作的基本实现
*/
public class Tea extends RefreshBeverage {
@Override
protected void brew() {
// TODO Auto-generated method stub
System.out.println("用80度的热水浸泡茶叶5分钟");
}
@Override
protected void addCondiments() {
// TODO Auto-generated method stub
System.out.println("加入柠檬");
}
}
public class Test {
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println("咖啡制备中...");
//调用模板方法
RefreshBeverage b1=new Coffee();
b1.prepareBeverageTemplate();
System.out.println("咖啡做好了!");
System.out.println("****************");
System.out.println("茶制备中...");
//调用模板方法
RefreshBeverage b2=new Tea();
b2.prepareBeverageTemplate();
System.out.println("茶做好了!");
}
}
输出:
咖啡制备中...
将水煮沸
用沸水冲泡咖啡
将饮料倒入杯中
加入糖和牛奶
咖啡做好了!
****************
茶制备中...
将水煮沸
用80度的热水浸泡茶叶5分钟
将饮料倒入杯中
加入柠檬
茶做好了!
2.3 钩子使子类更灵活
/*
* 抽象基类,为所有子类提供一个算法框架
* 提神饮料
*/
public abstract class RefreshBeverage {
//禁止子类对算法框架做任何的改变.Template模板
/*
* 制备饮料的模板方法
* 封装了所有子类共同遵循的算法框架
* ctrl+1 可以自动生成方法
*/
public final void prepareBeverageTemplate() {
//1.将水煮沸
boilWater();
//2.泡制饮料
brew();
//3.将饮料倒入杯中
pureInCup();
//用钩子函数来进行判断,是否需要加入调味料
if(isCondimentsNeed()) {
//4.加入调味料.
addCondiments();
}
}
/*
* 抽象的基本方法,加调料
*/
protected abstract void addCondiments();
/*
* 抽象的基本方法,泡制饮料
*/
protected abstract void brew() ;
private void pureInCup() {
// TODO Auto-generated method stub
System.out.println("将饮料倒入杯中");
}
/*
* 基本方法,将水煮沸。向下屏蔽细节
* 对所有子类而言是一个共同的行为,不必向子类做过多地开放。故用private进行修饰
*/
private void boilWater() {
// TODO Auto-generated method stub
System.out.println("将水煮沸");
}
/*
* Hook函数,钩子函数,提供一个默认或空的实现
* 具体的子类可以自行决定是否挂钩以及如何挂钩
* 询问用户是否加入调料
*/
protected boolean isCondimentsNeed() {
return true;
}
}
/*
* 具体子类,提供了茶制作的基本实现
*/
public class Tea extends RefreshBeverage {
@Override
protected void brew() {
// TODO Auto-generated method stub
System.out.println("用80度的热水浸泡茶叶5分钟");
}
@Override
protected void addCondiments() {
// TODO Auto-generated method stub
System.out.println("加入柠檬");
}
/*
* (non-Javadoc)
* @see com.imooc.pattern.template.RefreshBeverage#isCondimentsNeed()
* 子类通过覆盖的形式选择挂载钩子函数
*/
protected boolean isCondimentsNeed() {
return false;
}
}
输出:
茶制备中...
将水煮沸
用80度的热水浸泡茶叶5分钟
将饮料倒入杯中
茶做好了!
3. 模板方法模式总结
3.1 模板方法模式总结
模板方法模式的实现要素:抽象基类,具体子类
模板方法模式的实现要素
准备一个抽象类,将部分逻辑以具体方法的形式实现,然后声明一些抽象方法交由子类实现剩余逻辑,用钩子方法给予子类更大的灵活性。最后将方法汇总成一个不可改变的模板方法。
模板方法模式的适用场景
(1) 算法或操作遵循相似的逻辑
(2) 重构时把相同的代码抽取到父类中
(3) 重要、复杂的算法,核心算法设计为模板算法
模板方法模式的优点
(1) 封装性好
(2) 复用性好
(3) 屏蔽细节
(4) 便于维护
模板方式的缺点
(1)由于java语言的单继承性,使用模板方法的子类引入新继承的时候会遇到困难
3.2 行业案例分享