设计模式:模版模式(Template Pattern)
2015-11-25 20:52
204 查看
模版模式
又叫模板方法模式,在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以在不改变算法结构的情冴下,重新定义算法中的某些步骤。
我们使用冲泡咖啡和冲泡茶的例子
加工流程:
咖啡冲泡法:1.把水煮沸、2.用沸水冲泡咖啡、3.把咖啡倒进杯子、4.加糖和牛奶
茶冲泡法: 1.把水煮沸、2.用沸水冲泡茶叶、3.把 茶 倒进杯子、4.加蜂蜜
实践步骤:
1>创建一个模板(抽象)类:Beverage(饮料)
Java代码
package com.kaishengit.beverage;
public abstract class Beverage {
/**
* 冲泡咖啡或茶...流程
*/
public final void create(){
/*
所有的设计模式都遵循一个开闭原则:对修改关闭,对对扩展开放
所有被final标注的方法都是不能被继承、更改的,所以对于final方法 使用的第一个原因就是方法锁定,以防止任何子类来对它的修改。至于 第二个原因就是效率问题,在java的早期实现中,如果将一个方法指明为final,就是同意编译器将针对该方法的所有调用都转为内嵌调用。当编译器发现一个final方法调用命令时,它会根据自己的谨慎判断,跳过插入程序代码这种正常的调用方式而执行方法调用机制(将参数压入栈,跳至方法代码处执行,然后跳回并清理栈中的参数,处理返回值),并且以方法体中的实际代码的副本来代替方法调用。这将消除方法调用的开销。当然,如果一个方法很大,你的程序代码会膨胀,因而可能看不到内嵌所带来的性能上的提高,因为所带来的性能会花费于方法内的时间量而被缩减。*/
boilWater();//把水煮沸
brew();//用沸水冲泡...
pourInCup();//把...倒进杯子
addCoundiments();//加...
}
public abstract void addCoundiments();
public abstract void brew();
public void boilWater() {
System.out.println("煮开水");
}
public void pourInCup() {
System.out.println("倒进杯子");
}
}
2>创建一个咖啡类(Coffee)和茶(Tea)类,都继承Beverage抽象类
1.咖啡(Coffee)
Java代码
package com.kaishengit.beverage;
public class Coffee extends Beverage{
@Override
public void addCoundiments() {
System.out.println("添加糖和牛奶"); }
@Override
public void brew() {
System.out.println("用水冲咖啡");
}
}
2.茶(Tea)
Java代码
package com.kaishengit.beverage;
public class Tea extends Beverage{
@Override
public void addCoundiments() {
System.out.println("添加蜂蜜");
}
@Override
public void brew() {
System.out.println("用水冲茶");
}
}
3.我们测试一下:
Java代码
package com.kaishengit.beverage;
public class Test {
public static void main(String[] args) {
Coffee coffee = new Coffee();
coffee.create();//冲泡咖啡
//Tea tea = new Tea();//冲泡茶
//tea.create();
}
}
运行结果:
-----------------------------------
煮开水
用水冲咖啡
倒进杯子
添加糖和牛奶
-----------------------------------
在模版模式中使用挂钩(hook)
存在一个空实现的方法,我们称这种方法为”hook”。子类可以视情况来决定是否要覆盖它。
1>我们对模板类(Beverage)进行修改
Java代码
package com.kaishengit.beverage;
public abstract class Beverage {
/**
* 冲泡咖啡或茶...流程
*/
public final void create(){
boilWater();//把水煮沸
brew();//用沸水冲泡...
pourInCup();//把...倒进杯子
addCoundiments();//加...
hook();//挂钩
}
//空实现方法
public void hook(){}
public abstract void addCoundiments();
public abstract void brew();
public void boilWater() {
System.out.println("煮开水");
}
public void pourInCup() {
System.out.println("倒进杯子");
}
}
2>假如我们搞活动,喝一杯咖啡送一杯,修改咖啡(Coffee)类
Java代码
package com.kaishengit.beverage;
public class Coffee extends Beverage{
@Override
public void addCoundiments() {
System.out.println("添加糖和牛奶"); }
@Override
public void brew() {
System.out.println("用水冲咖啡");
}
/**
* 挂钩
*/
@Override
public void hook() {
System.out.println("再来一杯");
}
}
3>使用上面的测试类
运行结果:
--------------------------------
煮开水
用水冲咖啡
倒进杯子
添加糖和牛奶
再来一杯
--------------------------------
结果中有“再来一杯”...
我们也可以这样使用挂钩,让其决定里面的代码是否执行
1>我们对模板类(Beverage)进行修改
Java代码
package com.kaishengit.beverage;
public abstract class Beverage {
/**
* 冲泡咖啡或茶...流程
*/
public final void create(){
boilWater();//把水煮沸
brew();//用沸水冲泡...
pourInCup();//把...倒进杯子
//挂钩决定是否添加配料
if(hook()){
addCoundiments();//加...
}
//hook();
}
/**
* 默认添加配料
* @return
*/
public boolean hook() {
return true;
}
//public void hook(){}
public abstract void addCoundiments();
public abstract void brew();
public void boilWater() {
System.out.println("煮开水");
}
public void pourInCup() {
System.out.println("倒进杯子");
}
}
2>我们对Coffee类进行修改,让其不添加配料
Java代码
package com.kaishengit.beverage;
public class Coffee extends Beverage{
@Override
public void addCoundiments() {
System.out.println("添加糖和牛奶"); }
@Override
public void brew() {
System.out.println("用水冲咖啡");
}
/**
* 有的客人不喜欢加配料
*/
@Override
public boolean hook() {
return false;
}
/*@Override
public void hook() {
System.out.println("再来一杯");
}
*/
}
3>还是使用上面的测试类
运行结果:
------------------------------------------------------
煮开水
用水冲咖啡
倒进杯子
------------------------------------------------------
运行结果中没有添加配料
关于模板模式
1>模板模式定义了算法的步骤,把这些步骤的实现延迟到子类
2>模板模式为我们提供了一个代码复用的技巧
3>模板抽象类中可以定义具体方法、抽象方法和钩子方法
4>为了防止子类改变模板中的算法,可以将模板方法声明为final
5>钩子是一种方法,它在抽象类中不做事,或只做默认的事,子类可以选择要不要实现它
-----------end--------------
又叫模板方法模式,在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以在不改变算法结构的情冴下,重新定义算法中的某些步骤。
我们使用冲泡咖啡和冲泡茶的例子
加工流程:
咖啡冲泡法:1.把水煮沸、2.用沸水冲泡咖啡、3.把咖啡倒进杯子、4.加糖和牛奶
茶冲泡法: 1.把水煮沸、2.用沸水冲泡茶叶、3.把 茶 倒进杯子、4.加蜂蜜
实践步骤:
1>创建一个模板(抽象)类:Beverage(饮料)
Java代码
package com.kaishengit.beverage;
public abstract class Beverage {
/**
* 冲泡咖啡或茶...流程
*/
public final void create(){
/*
所有的设计模式都遵循一个开闭原则:对修改关闭,对对扩展开放
所有被final标注的方法都是不能被继承、更改的,所以对于final方法 使用的第一个原因就是方法锁定,以防止任何子类来对它的修改。至于 第二个原因就是效率问题,在java的早期实现中,如果将一个方法指明为final,就是同意编译器将针对该方法的所有调用都转为内嵌调用。当编译器发现一个final方法调用命令时,它会根据自己的谨慎判断,跳过插入程序代码这种正常的调用方式而执行方法调用机制(将参数压入栈,跳至方法代码处执行,然后跳回并清理栈中的参数,处理返回值),并且以方法体中的实际代码的副本来代替方法调用。这将消除方法调用的开销。当然,如果一个方法很大,你的程序代码会膨胀,因而可能看不到内嵌所带来的性能上的提高,因为所带来的性能会花费于方法内的时间量而被缩减。*/
boilWater();//把水煮沸
brew();//用沸水冲泡...
pourInCup();//把...倒进杯子
addCoundiments();//加...
}
public abstract void addCoundiments();
public abstract void brew();
public void boilWater() {
System.out.println("煮开水");
}
public void pourInCup() {
System.out.println("倒进杯子");
}
}
2>创建一个咖啡类(Coffee)和茶(Tea)类,都继承Beverage抽象类
1.咖啡(Coffee)
Java代码
package com.kaishengit.beverage;
public class Coffee extends Beverage{
@Override
public void addCoundiments() {
System.out.println("添加糖和牛奶"); }
@Override
public void brew() {
System.out.println("用水冲咖啡");
}
}
2.茶(Tea)
Java代码
package com.kaishengit.beverage;
public class Tea extends Beverage{
@Override
public void addCoundiments() {
System.out.println("添加蜂蜜");
}
@Override
public void brew() {
System.out.println("用水冲茶");
}
}
3.我们测试一下:
Java代码
package com.kaishengit.beverage;
public class Test {
public static void main(String[] args) {
Coffee coffee = new Coffee();
coffee.create();//冲泡咖啡
//Tea tea = new Tea();//冲泡茶
//tea.create();
}
}
运行结果:
-----------------------------------
煮开水
用水冲咖啡
倒进杯子
添加糖和牛奶
-----------------------------------
在模版模式中使用挂钩(hook)
存在一个空实现的方法,我们称这种方法为”hook”。子类可以视情况来决定是否要覆盖它。
1>我们对模板类(Beverage)进行修改
Java代码
package com.kaishengit.beverage;
public abstract class Beverage {
/**
* 冲泡咖啡或茶...流程
*/
public final void create(){
boilWater();//把水煮沸
brew();//用沸水冲泡...
pourInCup();//把...倒进杯子
addCoundiments();//加...
hook();//挂钩
}
//空实现方法
public void hook(){}
public abstract void addCoundiments();
public abstract void brew();
public void boilWater() {
System.out.println("煮开水");
}
public void pourInCup() {
System.out.println("倒进杯子");
}
}
2>假如我们搞活动,喝一杯咖啡送一杯,修改咖啡(Coffee)类
Java代码
package com.kaishengit.beverage;
public class Coffee extends Beverage{
@Override
public void addCoundiments() {
System.out.println("添加糖和牛奶"); }
@Override
public void brew() {
System.out.println("用水冲咖啡");
}
/**
* 挂钩
*/
@Override
public void hook() {
System.out.println("再来一杯");
}
}
3>使用上面的测试类
运行结果:
--------------------------------
煮开水
用水冲咖啡
倒进杯子
添加糖和牛奶
再来一杯
--------------------------------
结果中有“再来一杯”...
我们也可以这样使用挂钩,让其决定里面的代码是否执行
1>我们对模板类(Beverage)进行修改
Java代码
package com.kaishengit.beverage;
public abstract class Beverage {
/**
* 冲泡咖啡或茶...流程
*/
public final void create(){
boilWater();//把水煮沸
brew();//用沸水冲泡...
pourInCup();//把...倒进杯子
//挂钩决定是否添加配料
if(hook()){
addCoundiments();//加...
}
//hook();
}
/**
* 默认添加配料
* @return
*/
public boolean hook() {
return true;
}
//public void hook(){}
public abstract void addCoundiments();
public abstract void brew();
public void boilWater() {
System.out.println("煮开水");
}
public void pourInCup() {
System.out.println("倒进杯子");
}
}
2>我们对Coffee类进行修改,让其不添加配料
Java代码
package com.kaishengit.beverage;
public class Coffee extends Beverage{
@Override
public void addCoundiments() {
System.out.println("添加糖和牛奶"); }
@Override
public void brew() {
System.out.println("用水冲咖啡");
}
/**
* 有的客人不喜欢加配料
*/
@Override
public boolean hook() {
return false;
}
/*@Override
public void hook() {
System.out.println("再来一杯");
}
*/
}
3>还是使用上面的测试类
运行结果:
------------------------------------------------------
煮开水
用水冲咖啡
倒进杯子
------------------------------------------------------
运行结果中没有添加配料
关于模板模式
1>模板模式定义了算法的步骤,把这些步骤的实现延迟到子类
2>模板模式为我们提供了一个代码复用的技巧
3>模板抽象类中可以定义具体方法、抽象方法和钩子方法
4>为了防止子类改变模板中的算法,可以将模板方法声明为final
5>钩子是一种方法,它在抽象类中不做事,或只做默认的事,子类可以选择要不要实现它
-----------end--------------
相关文章推荐
- UVA1511 Buy or Build 二进制枚举+最小生成树kruskal
- netty5学习笔记-内存池5-PoolThreadCache
- CC2530在IAR编辑时候8.10和8.20版本之间的兼容性问题
- VisualStudioOnline协同工作流程
- UIScrollView视差效果动画
- FreeMarker导出word,解决\n换行问题
- JSP通过IP获取用户(客户端)的地理位置信息
- CodeUI Test:UIMap录制文件分析一
- Highcharts ajax获取json对象动态生成报表生成 .
- 树的直径 poj1985 poj 1849 hdu 2196
- CCNA学习笔记二 IP编址、子网划分、思科路由器基础操作
- C++11中的POD和Trivial
- MySQL索引背后的数据结构及算法原理
- iOS 开发之封装
- identifier标签语句
- #pragma 的使用(c/c++)【转】
- 从一个玩家的角度来说说我想做什么样的游戏
- android studio 中去除应用标题栏
- 一个理工男的十年(二)
- 个人商家怎么申请微信支付接口