十、模板方法模式—制作更多好喝的饮品! #和设计模式一起旅行#
无规矩不成方圆!
故事背景
在安装了酷炫了碉堡了的灯之后,我和设计模式MM经营的奶茶店生意更加火爆,有不同国家的顾客,那么为了满足更多消费者的口味,我们推出了中国龙井苹果茶和叶门摩卡牛奶咖啡。其中制作的过程:
- 把水烧开
- 将咖啡/茶叶放到杯子里
- 用沸水冲泡
- 加入牛奶/苹果汁
下面用代码来表示茶和咖啡的制作过程!
//龙井苹果茶制作
public class LongJinTea {/*** 制作方法*/public void makeMethod(){boliWater();putMaterialToCup();pourInCup();addAppleJuice();}/*** 烧水*/private void boliWater() {System.out.println("---将水煮沸-----");}/*** 将原料放入杯子*/private void putMaterialToCup() {System.out.println("---将龙井茶叶放入杯子中-----");}/*** 用沸水冲泡*/private void pourInCup() {System.out.println("---将沸水倒入杯子-----");}/*** 加入苹果汁*/private void addAppleJuice() {System.out.println("---在浸泡龙井茶叶的杯子中加入苹果汁-----");}}//摩卡牛奶咖啡
public class MOKACoffee {/*** 制作方法*/public void makeMethod(){boliWater();putMaterialToCup();pourInCup();addMilk();}/*** 烧水*/private void boliWater() {System.out.println("---将水煮沸-----");}/*** 将原料放入杯子*/private void putMaterialToCup() {System.out.println("---将咖啡放入杯子中-----");}/*** 用沸水冲泡*/private void pourInCup() {System.out.println("---将沸水倒入杯子-----");}/*** 加入牛奶*/private void addMilk() {System.out.println("---在浸泡咖啡的杯子中加入牛奶-----");}
}
设计模式MM:
1. 上面的代码我发现很多重复的代码啊!这个咖啡和茶的制作过程如此相似,应该考虑抽取共同部分,放入一个基类中。
2. 上面的整个制作流程其实可以看做是一个算法的步骤,这几个步骤的次序是:①烧水 –> ②往杯子放原料 –> ③加入沸水—> ④加入其它添加物,其中只有②和④不同。
建议你去看看模板方法模式!
我: 好的!
故事主角-模板方法模式
模板方法模式:在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构的情况下,重新定义的算法中某些步骤。
模板方法模式是一种基础继承的代码复用技术。
模板方法模式包含两个角色:
- AbstractClass(抽象类):这个抽象类包含了一个模板方法,在这个模板方法的一系列方法可以是具体的,也可以是抽象的,每个基本的操作对应算法的一个步骤,其中抽象的步骤由子类定义实现。
- ConcreteClass(具体子类):抽象类的子类,用于实现父类模板方法中算法的步骤,也可以覆盖父类中已经实现的基本操作。
模板方法模式的实现
模板中定义了一个算法的框架,其中包括:
1.模板方法
把基本操作方法组合在一起形成一个总算法或一个总行为的方法!这个模板方法定义在抽象类中,由子类不加以修改的完全继承!
2.基本方法
基本方法实现算法各个步骤的方法,是模板方法的组成部分。基本方法有可以分为三种:
(1) 抽象方法(AbstractMethod)
(2) 具体方法(ConcreteMethod)
(3) 钩子方法(HookMethod)
(1)抽象方法(AbstractMethod):抽象类申明一个抽象方法,由其子类去实现。
(2)具体方法(ConcreteMethod):抽象类申明并实现一个具体方法,也可以由子类进行覆盖。
(3)钩子方法(HookMethod):抽象类申明并实现一个钩子方法,抽象类一般可以订阅为空实现。可以由其子类加以扩展。
在模板方法模式中,程序在运行时,具体子类的基本方法可以覆盖父类中定义的基本方法,子类的钩子方法也可以覆盖父类的钩子方法,从而可以通过在子类中实现的钩子方法对父类方法的执行进行约束,实现子类对父类行为的反向控制。【现在在武功修改中讲解这一话的意思】
武功修炼
public abstract class GreatBeverage {/*** 制作最棒饮品的模板方法*/public final void makeBeverage(){boliWater();putMaterialToCup();pourInCup();addCondiments();}/*** 烧水*/public void boliWater() {System.out.println("---将水煮沸-----");}/*** 将原料放入杯子*/public abstract void putMaterialToCup() ;/*** 用沸水冲泡*/public void pourInCup() {System.out.println("---将沸水倒入杯子-----");}/*** 加入饮品的调味品*/public abstract void addCondiments();
}//龙井苹果茶制作
public class LongJinTea extends GreatBeverage {/*** 将原料放入杯子*/@Overridepublic void putMaterialToCup() {System.out.println("---将龙井茶叶放入杯子中-----");}/*** 加入苹果汁*/@Overridepublic void addCondiments() {System.out.println("---在浸泡龙井茶叶的杯子中加入苹果汁-----");}}//摩卡牛奶咖啡
public class MOKACoffee extends GreatBeverage{/*** 将原料放入杯子*/@Overridepublic void putMaterialToCup() {System.out.println("---将咖啡放入杯子中-----");}/*** 加入牛奶*/@Overridepublic void addCondiments() {System.out.println("---在浸泡咖啡的杯子中加入牛奶-----");}
}public class Test {public static void main(String[] args) {//来了个叶门顾客GreatBeverage gb = new LongJinTea();gb.makeBeverage();//制作龙井苹果茶System.out.println("==============华丽的分割线===========");//来了一个中国顾客gb = new MOKACoffee();//制作摩卡牛奶咖啡gb.makeBeverage();}
}---将水煮沸-----
---将龙井茶叶放入杯子中-----
---将沸水倒入杯子-----
---在浸泡龙井茶叶的杯子中加入苹果汁-----
==============华丽的分割线===========
---将水煮沸-----
---将咖啡放入杯子中-----
---将沸水倒入杯子-----
---在浸泡咖啡的杯子中加入牛奶-----
目前我们买的龙井苹果茶或者摩卡牛奶咖啡都是假如了调味料,为了人性化,提示顾客的品味体验,我们会在制作的时候咨询顾客是否需要假如调味料,那么我们改怎么实现呢?【这里就使用到上面的钩子方法】,在泡茶的水使用高端设备进行烧水。
具体的代码如下:
public abstract class GreatBeverage {/*** 制作最棒饮品的模板方法*/public final void makeBeverage(){boliWater();putMaterialToCup();pourInCup();if(isAddCondiment()){//加上判断,可以由具体方法进行判断决定addCondiments();}}/*** 烧水*/public void boliWater() {System.out.println("---将水煮沸-----");}/*** 将原料放入杯子*/public abstract void putMaterialToCup() ;/*** 用沸水冲泡*/public void pourInCup() {System.out.println("---将沸水倒入杯子-----");}/*** 加入饮品的调味品*/public abstract void addCondiments();/*** 钩子方法,默认实现* @return*/public boolean isAddCondiment(){return true;}
}
//龙井苹果茶制作
public class LongJinTea extends GreatBeverage {/*** 以覆盖父类中定义的基本方法*/@Overridepublic void boliWater(){System.out.println("----泡茶使用高端的热水设备进行烧水---");}/*** 将原料放入杯子*/@Overridepublic void putMaterialToCup() {System.out.println("---将龙井茶叶放入杯子中-----");}/*** 加入苹果汁*/@Overridepublic void addCondiments() {System.out.println("---在浸泡龙井茶叶的杯子中加入苹果汁-----");}@Overridepublic boolean isAddCondiment(){String answer = getUserAnswer();if("加".equals(answer)){return true;}else if("不加".equals(answer)){return false;}else{//随便return true;}}private String getUserAnswer() {System.out.println("你好,你要在龙井茶中加入苹果汁吗?");BufferedReader in = null;String answer = null;try {in = new BufferedReader(new InputStreamReader(System.in));answer = in.readLine();}catch (IOException e){e.printStackTrace();}finally {if (in != null) {try {in.close();} catch (IOException e) {e.printStackTrace();}}}return answer;}}public class Test {public static void main(String[] args) {//来了个叶门顾客GreatBeverage gb = new LongJinTea();gb.makeBeverage();//制作龙井苹果茶}
}----泡茶使用高端的热水设备进行烧水---
---将龙井茶叶放入杯子中-----
---将沸水倒入杯子-----
你好,你要在龙井茶中加入苹果汁吗?
不加Process finished with exit code 0----泡茶使用高端的热水设备进行烧水---
---将龙井茶叶放入杯子中-----
---将沸水倒入杯子-----
你好,你要在龙井茶中加入苹果汁吗?
加
---在浸泡龙井茶叶的杯子中加入苹果汁-----Process finished with exit code 0
上面的这一段代码实例就解释 了,在模板方法模式中,程序在运行时,具体子类的基本方法可以覆盖父类中定义的基本方法,子类的钩子方法也可以覆盖父类的钩子方法,从而可以通过在子类中实现的钩子方法对父类方法的执行进行约束,实现子类对父类行为的反向控制。
注意:为了防止子类去修改模板方法中的算法结构,可以将模板方法设置为final。
武功深入 - 模板方法模式和策略模式比较
模板方法模式:
- 定义一个算的大纲,由子类去实现算法大纲中某些步骤内容,虽然算法中个别步骤可以由不同的实现,但整体的算法结构维持不变。
- 使用继承方式,对算法有更多的控制权,实现代码复用
- 使用较多的模式
策略模式:
- 定义一个算法家族,并让算法之间可以互换
- 使用对象对象组合,更有弹性
武功应用场景思考
根据模板方法模式设计一个电商系统付款场景,比如付款可以是微信、支付宝、银联!
思路提示 - 付款简单包含:参数检验 、 调用支付请求、返回结果处理、回调的操作等
JDK、Tomcat、Spring等中哪些地方使用到了模板方法模式?
思路提示: JDK的ClassLoader;JDK中CompareTo的实现(符合模板方法的精神);Tomcat中关于生命周期管理的地方很好应用了模板方法模式;Spring中的JdbcTemplate。
Next 期待下一篇吧!制作更多好喝的饮品!我的这个旅行创业成功后,很多媒体活动需要参加,那么我要对接很多活动和处理很多问题。于是我想请一个助理,代理我做一些接活动和处理问题的事情,我只负责参加活动即可!下一篇:代理模式,解放自己,让我能更加专注核心业务处理。
参考
- 史上最全设计模式导学
- 《Head First 设计模式》
- 《图解设计模式》
本专栏文章列表
一、设计模式-开篇—为什么我要去旅行? #和设计模式一起旅行#
二、设计模式-必要的基础知识—旅行前的准备 #和设计模式一起旅行#
三、设计模式介绍—她是谁,我们要去哪里? #和设计模式一起旅行#
四、单例模式—不要冒充我,我只有一个! #和设计模式一起旅行#
五、工厂模式—旅行的钱怎么来 #和设计模式一起旅行#
六、策略模式—旅行的交通工具 #和设计模式一起旅行#
七、观察者模式——关注我,分享旅途最浪漫的瞬间! #和设计模式一起旅行#
八、装饰者模式—巴厘岛,奶茶店的困扰! #和设计模式一起旅行#
九、命令模式—使用命令控制奶茶店中酷炫的灯 #和设计模式一起旅行#
十、模板方法模式—制作更多好喝的饮品! #和设计模式一起旅行#
十一、代理模式 —专注,做最好的自己!#和设计模式一起旅行#
十二、适配器模式——解决充电的烦恼 #和设计模式一起旅行#
十三、外观模式—— 简化接口 #和设计模式一起旅行#
十四、迭代器模式—— 一个一个的遍历 #和设计模式一起旅行#
十五、组合模式—— 容器与内容的一致性 #和设计模式一起旅行#
十六、状态模式—用类表示状态 #和设计模式一起旅行#
十七、访问者模式-访问数据结构并处理数据 #和设计模式一起旅行#
十八、职责链模式-推卸责任,不关我的事,我不管!#和设计模式一起旅行#
十九、原型模式—通过复制生产实例 #和设计模式一起旅行#
二十、设计模式总结—后会有期 #和设计模式一起旅行#
如果您觉得这篇博文对你有帮助,请点赞或者喜欢,让更多的人看到,谢谢!
如果帅气(美丽)、睿智(聪颖),和我一样简单善良的你看到本篇博文中存在问题,请指出,我虚心接受你让我成长的批评,谢谢阅读!
祝你今天开心愉快!
欢迎访问我的csdn博客,我们一同成长!
不管做什么,只要坚持下去就会看到不一样!在路上,不卑不亢!
博客首页 : http://blog.csdn.net/u010648555
十、模板方法模式—制作更多好喝的饮品! #和设计模式一起旅行#相关推荐
- 十二、适配器模式——解决充电的烦恼 #和设计模式一起旅行#
轻轻的我走了, 正如我轻轻的来: 我轻轻的招手, 作别西天的云彩. --徐志摩 <再别康桥> 故事背景 把奶茶店盘了出去,我和设计模式MM,继续上路,坐着冒着烟的飞机来到了剑桥,这里真是个 ...
- 十八、职责链模式-推卸责任,不关我的事,我不管!#和设计模式一起旅行#
不在其位,不谋其政! –出自<论语·泰伯> 故事背景 在现实世界中,有很多情况下会遇到一些推卸责任的场景,比如要办理一件事的时候,被告诉你要去做个做这个事情,但是去了这个地方,确告诉要到另 ...
- 六、策略模式—旅行的交通工具 #和设计模式一起旅行#
兵无常势,水无常形,能因敌变化而取胜者,谓之神! --<孙子兵法> 故事背景 旅行开始,我和设计模式mm要去的目的地很多,去往不同目的地可以选择的交通工具也是多样的,从北京到上海,我们可以 ...
- 五、工厂模式—旅行的钱怎么来 #和设计模式一起旅行#
君子爱财,取之有道!-- 出自<增广贤文> 故事背景 上一篇我和MM相约好了,去旅行了,但是旅行是需要Money的啊,作为有个搬砖的码农,没钱啊,怎么呢!不能穷游啊,真是愁人啊 !哎 ,办 ...
- 八、装饰者模式—巴厘岛,奶茶店的困扰! #和设计模式一起旅行#
善于思考,方法总比问题多! 故事背景 我和漂亮的模式MM来到巴厘岛,这里火山爆发刚刚结束不久,一切要重新开始,来到这个地方几天后,觉得这个地方还是不错,于是就决定在这里开一个奶茶店,因为这里游客比较多 ...
- 从模板方法模式到JDBCTemplate
将大象装进冰箱需要三步,那么老虎了?如何优雅的将大象装进冰箱? 把大象装进冰箱 Step 大象 老虎 ... First 打开冰箱门 打开冰箱门 打开冰箱门 Second 把大象放进去 把老虎放进去 ...
- Windows环境下实现设计模式——模板方法模式(JAVA版)
我是荔园微风,作为一名在IT界整整25年的老兵,今天总结一下Windows环境下如何编程实现模板方法模式(设计模式). 不知道大家有没有这样的感觉,看了一大堆编程和设计模式的书,却还是很难理解设计模式 ...
- 小话设计模式五:模板方法模式
模板方法模式定义: 定义一个操作中的算法骨架,而将一些实现步骤延迟到子类当中.模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤. 模板方法解析: 模板方法模式是比较简单的一种设计 ...
- 设计模式之模板方法模式(附应用举例实现)
文章目录 1 模板方法模式介绍 2 模板方法模式详解 2.1 模板方法模式结构 2.2 模板方法模式实现 2.3 模板方法模式应用举例 1 模板方法模式介绍 在软件开发中,某个方法的实现需要多个步骤, ...
- 模板方法模式 Template method 行为型 设计模式(二十六)
模板方法模式 Template method 上图为网上百度的一份简历模板截图 相信大家都有求职的经历,那么必然需要简历,写简历的时候,很可能你会网上检索一份简历模板,使用此模板的格式,然后替换为你的 ...
最新文章
- 使用roslyn代替MSBuild完成解决方案编译
- win10 安装字体且不占用系统盘资源
- 获2017中国最佳创业投资机构百强,西高投二次创业实现超越
- python更新_MacOS升级python版本
- OpenCV-Python教程8-图像混合
- Visual Studio 2013 各个版本的产品密钥
- Android studio安装,提示haxm device is not found 需要下载微软补丁 完美解决
- 网吧游戏服务器制作教程,网吧服务器系统环境部署
- jest中的mock,jest.fn()、jest.spyOn()、jest.mock()
- 开发与研发:区别很大(上)
- 2016年中国未来的新兴行业推荐
- 基于RWEQ模型的土壤风蚀模数估算及其变化归因分析
- android 小米8底部有一大片黑色
- excel和python建模_如何用Python提高办公(Excel)效率?
- 问题2:路径级别不清楚
- 抖音这样拍摄短视频,能让你轻松上热门涨粉丨国仁网络资讯
- 汽车行业信息化机遇与挑战
- 根据快递单号,生成快递单号
- scrapy实例 ----- 爬取小说
- 2022年深圳技能大赛-大数据技术应用职业技能竞赛介绍
热门文章
- python 计算 换手率_python数据统计告诉你,是不是周四周五会跌的比较多
- 记录一个docker启动容器报的错Error response from daemon: OCI runtime create failed: container_linux.go:349
- MVC升级swagger No operations defined in spec!
- Java多线程-生产者消费者案例
- Opencv c++对比度增强(1.多尺度Retinex;2.LICE-Retinex;3.自适应对数映射。)
- nginx盗链与防盗链,nginx的平滑升级
- 为什么python如此火爆_用Python来分析一波周董新曲《说好不哭》为何如此火爆!...
- 如何在浏览器中快速切换搜索引擎
- 数的读法c语言程序,[蓝桥杯]数的读法-笨办法(C语言)
- 深度学习实战之【电影评论分类】:二分类问题