模板方法模式学习笔记
2015-06-10 10:00
477 查看
模板方法的实现要素:抽象基类和具体子类。
抽象基类:(1)基本方法:共有的方法,用private修饰
(2)抽象方法:只知道原则,不知道具体实现,要延迟到子类中实现,用protected abstract修饰
(3)可选的钩子:具体的子类可以自行决定是否挂钩以及如何挂钩,从而影响算法的实现,用protected修饰
(4)Template方法:封装了所有子类共同遵循的算法框架,用final修饰,不让子类覆盖重写。
模板方法定义成final,即表示子类可以替换掉父类中的可变逻辑,但不能改变掉整体逻辑结构。(好莱坞原则)
具体子类:(1)实现基类中的抽象方法
(2)可选的覆盖钩子方法,来更加个性化来影响算法的局部行为。
总结:
准备一个抽象类,将部分逻辑以具体方法的形式实现,然后声明一些抽象方法交由子类实现剩余逻辑,用钩子方法给予子类更大的灵活性。最后将方法汇总构成一个不可改变的模板方法。
模板方法模式的适用场景:
(1)算法或操作遵循相似的逻辑
(2)重构时(把相同的代码抽取到父类中)
(3)重要,复杂的算法,核心算法设计为模板算法
模板方法模式的优点:
(1)封装性好
(2)复用性好
(3)屏蔽细节
(4)便于维护
模板方法模式的缺点:
4000
(1)继承(Java语言只支持单继承),但我们重构一个系统时,假如有些类已经继承了相关父类,那就无法再继承模板方法的抽象基类。
简单代码示例如下:
抽象基类:(1)基本方法:共有的方法,用private修饰
(2)抽象方法:只知道原则,不知道具体实现,要延迟到子类中实现,用protected abstract修饰
(3)可选的钩子:具体的子类可以自行决定是否挂钩以及如何挂钩,从而影响算法的实现,用protected修饰
(4)Template方法:封装了所有子类共同遵循的算法框架,用final修饰,不让子类覆盖重写。
模板方法定义成final,即表示子类可以替换掉父类中的可变逻辑,但不能改变掉整体逻辑结构。(好莱坞原则)
具体子类:(1)实现基类中的抽象方法
(2)可选的覆盖钩子方法,来更加个性化来影响算法的局部行为。
总结:
准备一个抽象类,将部分逻辑以具体方法的形式实现,然后声明一些抽象方法交由子类实现剩余逻辑,用钩子方法给予子类更大的灵活性。最后将方法汇总构成一个不可改变的模板方法。
模板方法模式的适用场景:
(1)算法或操作遵循相似的逻辑
(2)重构时(把相同的代码抽取到父类中)
(3)重要,复杂的算法,核心算法设计为模板算法
模板方法模式的优点:
(1)封装性好
(2)复用性好
(3)屏蔽细节
(4)便于维护
模板方法模式的缺点:
4000
(1)继承(Java语言只支持单继承),但我们重构一个系统时,假如有些类已经继承了相关父类,那就无法再继承模板方法的抽象基类。
简单代码示例如下:
/** * 抽象基类,为所有子类提供一个算法框架 * * 提神饮料 * * @author zhx * */ public abstract class RefreshBeverage { /* * 制备饮料的模版方法 封装了所有子类共同遵循的算法框架 */ public final void prepareBeverageTemplate() { // 步骤1:将水煮沸 boilWater(); // 步骤2:泡制饮料 brew(); // 步骤3:将饮料倒入杯中 pourInCup(); if(isCustomerWantsCondiments()) { // 步骤4:加入调味料 addCondiments(); } } /* * Hook,钩子函数,提供一个默认或空的实现 * 具体的子类可以自行决定是否挂钩以及如何挂钩 * 询问用户是否加入调料 */ protected boolean isCustomerWantsCondiments() { return true; } /* * 基本方法,将水煮沸 */ private void boilWater() { System.out.println("将水煮沸"); } /* * 抽象的基本方法,泡制饮料 */ protected abstract void brew(); /* * 基本方法,将饮料倒入杯中 */ private void pourInCup() { System.out.println("将饮料倒入杯中"); } /* * 抽象的基本方法:加入调味料 */ protected abstract void addCondiments(); } /** * 具体子类,提供了制备咖啡的具体实现 * @author zhx * */ public class Coffee extends RefreshBeverage { @Override protected void brew() { System.out.println("用沸水冲泡咖啡"); } @Override protected void addCondiments() { System.out.println("加入糖和牛奶"); } } /** * 具体子类:提供了制备茶的具体实现 * @author zhx * */ public class Tea extends RefreshBeverage{ @Override protected void brew() { System.out.println("用80℃的热水浸泡茶叶5分钟"); } @Override protected void addCondiments() { System.out.println("加入柠檬"); } /* * 子类通过覆盖的形式选择挂载钩子函数 * @see edu.bnuz.zhx.design_pattern.template.RefreshBeverage#isCustomerWantsCondiments() */ @Override protected boolean isCustomerWantsCondiments() { return false; } } public class RefreshBeverageTest { public static void main(String[] args) { System.out.println("制备咖啡中..."); RefreshBeverage coffee = new Coffee(); coffee.prepareBeverageTemplate(); System.out.println("咖啡制备完成..."); System.out.println("-----------------------------------"); System.out.println("制备茶中..."); RefreshBeverage tea = new Tea(); tea.prepareBeverageTemplate(); System.out.println("茶制备完成..."); } }
相关文章推荐
- N-Queens
- android之存储篇_SQLite数据库_让你彻底学会SQLite的使用
- H.264(MPEG-4 AVC)级别(Level),DPB与MaxDpbMbs详解
- 无数美女泣血总结:千万不要嫁给程序猿
- 高德地图infowindow点击其他地方消失
- 学生选课数据库(oracle 11g)的设计与管理
- windows下PHP Pthreads多线程安装与配置
- 模板方法模式学习笔记
- 常用jQuery代码03
- PHP array_fill()
- jQuery.extend 函数详解
- 3DES加密和解密的实例
- MySQL的错误码
- 升级ADT22.6后,Android模拟器无法创建
- 银航时时彩-天恒PHP版本-时时彩源码程序完整下载
- 【最小生成树】BZOJ1016: [JSOI2008]最小生成树计数
- JSP+JavaBean
- 图解后缀表达式的计算过程
- Hibernate各种主键生成策略与配置详解
- Hibernate各种主键生成策略与配置详解