瑞幸咖啡还是星巴克,一杯下午茶让我明白 设计模式--模板方法模式(Template Method Pattern)

简介
Define the skeleton of an algorithm in an operation,deferring some
steps to subclasses.Template Method lets subclasses redefine certain
steps of an algorithm without changing the algorithm’s structure.
定义一个操作中的算法的框架,而将一些步骤延迟到子类中。使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
-----------------------------------------------------------------深入浅出的设计模式
模板方法模式(Template Method Pattern) 实际上是封装了一个固定流程,该流程由几个步骤组成,具体步骤可以由子类进行不同实现,从而让固定的流程产生不同的结果。
意图:定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
模板方法模式实际上是所有模式中最为常见的几个模式之一,而且很多人可能使用过模板方法模式而没有意识到自己已经使用了这个模式。模板方法模式是基于继承的代码复用的基本技术,模板方法模式的结构和用法也是面向对象设计的核心。模板方法的本质:抽象封装流程,具体进行实现
模版方法模式需要开发抽象类和具体子类的设计师之间的协作。
- 一个设计师负责给出一个算法的轮廓和骨架
- 另一些设计师则负责给出这个算法的各个逻辑步骤。
- 代表这些具体逻辑步骤的方法称做基本方法(primitive method)
- 将这些基本方法总汇起来的方法叫做模版方法(template method),这个设计模式的名字就是从此而来。
主要解决
当完成一个操作具有固定的流程时,由抽象固定流程步骤,具体步骤交给子类进行具体实现(固定的流程,不同的实现)。
优缺点
优点
- 封装不变,扩展可变:父类封装了具体流程以及实现部分不变行为,其它可变行为交由子类进行具体实现;
- 流程由父类控制,子类进行实现:框架流程由父类限定,子类无法更改;子类可以针对流程某些步骤进行具体实现;
- 提取公共代码,便于维护
缺点
- 抽象规定了行为,具体负责实现,与通常事物的行为相反,会带来理解上的困难(通俗地说,“父类调用了子类方法”);
- 每一个不同的实现都需要一个子类来实现,导致类的个数增加,使得系统更加庞大。
使用场景
当我们要完成在某一细节层次一致的一个过程或一系列步骤,但其个别步骤在更详细的层次上的实现可能不同的时候,我们通常要考虑用模板方法模式解决。
- 多个子类有公有的方法,并且逻辑基本相同时;
- 重要,复杂的算法,可以把核心算法设计为模板方法,周边的相关细节功能则由各个子类实现;
- 重构时,模板方法模式 是一个经常使用的模式,把相同的代码抽取到父类,然后通过钩子函数约束其行为;
注意事项: 为防止恶意操作,一般模板方法都加上 final 关键词。
模式讲解
首先来看下 模板方法模式 的通用 UML 类图:

模板方法模式
从 UML 类图中,我们可以看到,模板方法模式 主要包含两种角色:
抽象模板(AbstractClass): 抽象模板类,定义了一套算法框架/流程;
具体实现(ConcreteClass): 具体实现类,对算法框架/流程的某些步骤进行了实现;
当然这只是书面上的定义,用起来你会发现,为什么变得很复杂,好像更难了一样,你也有很多疑问?

- 在抽象类中只能定义抽象函数吗?
不是!看使用场景第三条! - 每一个抽象子类都要具体实现吗?
语法上是的,但逻辑上,可以Do nothing - 依据第一问,我能否对非抽象方法重写?
当然,语法上可以,而且逻辑上也可以。
最后,设计模式给出的是一种设计框架,而不是条条框框,你需要用的是他真正优秀的地方!
开发实例

就一杯下午茶,我到底和咖啡还是喝茶,喝咖啡,瑞幸还是星巴克?:

抽象类:
abstract class AbstractClass {
protected void Boil_water() {
System.out.println("SpecificMethod:烧水,倒一杯热水");
/*
* 模板方法的抽象类中,也是可以定义具体方法的,
* 一般子类中都具备或大部分中都具备时,放到抽象父类中。
*/
}
// 需要子类必须实现的需要写成抽象类
protected abstract void Abstract_step1();
protected abstract void Abstract_step2();
protected void Drink() {
System.out.println("SpecificMethod:吹一吹再喝,别烫着!");
}
// 声明为final方法,避免子类覆写
public final void After_Tea() {//来一杯下午茶吧
this.Boil_water();
this.Abstract_step1();
this.Abstract_step2();
this.Drink();
}
}
我要喝咖啡
class Concrete_Cof extends AbstractClass {
@Override
// 具体实现,重写父类抽象方法
protected void Abstract_step1() {
System.out.println("把咖啡豆磨好,倒进杯子里");
}
@Override
protected void Abstract_step2() {
System.out.println("加入方糖和奶精");
}
}
我要喝茶
class Concrete_Tea extends AbstractClass {
@Override
protected void Abstract_step1() {
System.out.println("把茶饼分开,放进杯子里");
}
@Override
protected void Abstract_step2() {
//Do nothing
//可以写成这种什么都没有的,毕竟喝茶我什么都不加(手动狗头)
}
}
我要喝奶茶
public class Concrete_MilkTea extends AbstractClass {
protected void Boil_water() {
System.out.println("煮一杯热牛奶");
}
@Override
protected void Abstract_step1() {
System.out.println("把茶饼分开,放进杯子里,过滤");
}
@Override
protected void Abstract_step2() {
System.out.println("加入方糖和香精");
}
}
class Client {
public static void main(String[] args) {
AbstractClass abc = new Concrete_Cof();
abc.After_Tea();
System.out.println("----------Next day-------------");
abc=new Concrete_Tea();
abc.After_Tea();
System.out.println("----------Next day-------------");
abc=new Concrete_MilkTea();
abc.After_Tea();
}
}
运行结果:


码字这么卖力,麻烦点个赞,点个关注,谢谢。
写在最后:
我叫风骨散人,名字的意思是我多想可以不低头的自由生活,可现实却不是这样。家境贫寒,总得向这个世界低头,所以我一直在奋斗,想改变我的命运给亲人好的生活,希望同样被生活绑架的你可以通过自己的努力改变现状,深知成年人的世界里没有容易二字。目前是一名在校大学生,预计考研,热爱编程,热爱技术,喜欢分享,知识无界,希望我的分享可以帮到你!
如果有什么想看的,可以私信我,如果在能力范围内,我会发布相应的博文!
感谢大家的阅读!瑞幸咖啡还是星巴克,一杯下午茶让我明白 设计模式--模板方法模式(Template Method Pattern)的更多相关文章
- 如何获取(GET)一杯咖啡——星巴克REST案例分析
英文原文:How to GET a Cup of Coffee 我们已习惯于在大型中间件平台(比如那些实现CORBA.Web服务协议栈和J2EE的平台)之上构建分布式系统了.在这篇文章里,我们将采取另 ...
- 杂项-公司:星巴克百科-un
ylbtech-杂项-公司:星巴克百科 星巴克(Starbucks)是美国一家连锁咖啡公司的名称,1971年成立,是全球最大的咖啡连锁店,其总部坐落美国华盛顿州西雅图市.星巴克旗下零售产品包括30多款 ...
- pyecharts实现星巴克门店分布可视化分析
项目介绍 使用pyecharts对星巴克门店分布进行可视化分析: 全球门店分布/拥有星巴克门店最多的10个国家或地区: 拥有星巴克门店最多的10个城市: 门店所有权占比: 中国地区门店分布热点图. 数 ...
- 【分享】纯jQuery实现星巴克官网导航栏效果
前言 大冬天的没得玩,只能和代码玩. 所以就无聊研究了一下星巴克官网,在我看来应该是基本还原吧~ 请各位大神指教! 官网效果图 要写的就是最上方的会闪现的白色条条 效果分析 1.在滚动条往下拉到一定距 ...
- 【方法】纯jQuery实现星巴克官网导航栏效果
前言 大冬天的没得玩,只能和代码玩. 所以就无聊研究了一下星巴克官网,在我看来应该是基本还原吧~ 请各位大神指教! 官网效果图 要写的就是最上方的会闪现的白色条条 效果分析 1.在滚动条往下拉到一定距 ...
- pandas实战——对星巴克数据的分析
一.实验对象 实验对象为星巴克在全球的门店数据,我们可以使用pandas对其进行简单的分析,如分析每个国家星巴克的数量,根据门店数量对国家进行排序等. 二.数据分析 1.读取数据并获取数据行列数 首先 ...
- 《Head First 设计模式》之模板方法模式——冲泡咖啡和茶
模板方法模式(Template) ——在一个方法中定义了一个算法的骨架,而将一些步骤延迟到子类中.模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤. 好莱坞原则:别调用(打电话给 ...
- 使用bs4中的方法爬取星巴克数据
import urllib.request # 请求url url = 'https://www.starbucks.com.cn/menu/' # 模拟浏览器发出请求 response = urll ...
- 深入浅出设计模式——模板方法模式(Template Method Pattern)
模式动机 模板方法模式是基于继承的代码复用基本技术,模板方法模式的结构和用法也是面向对象设计的核心之一.在模板方法模式中,可以将相同的代码放在父类中,而将不同的方法实现放在不同的子类中.在模板方法模式 ...
随机推荐
- MTK Android 读取SIM卡参数,获取sim卡运营商信息
android 获取sim卡运营商信息(转) TelephonyManager tm = (TelephonyManager)Context.getSystemService(Context.TE ...
- Linux服务器架设篇,Nginx服务器的架设
1.安装 nginx依赖包 (1)安装pcre yum install pcre-devel (2)安装openssl yum -y install openssl-devel (3)安装zlib y ...
- ListView + ArrayAdapter + 接口回调
众所周知,ListView是安卓最为频繁使用的控件,但是,随着人们审美观的提高,一些初级的ListView已经满足不了需求了,于是,我们必须为自己定制一套专属的ListView,这就需要用到适配器,A ...
- ssm整合简单例子
1.首先新建一个maven项目 2.在pom.xml文件中加入以下代码引入包 <properties> <project.build.sourceEncoding>UTF-8& ...
- 萌新带你开车上p站(三)
本文作者:萌新 前情回顾: 萌新带你开车上p站(一) 萌新带你开车上p站(二) 0x08 题目给的提示是和运算符优先级有关 登录后直接看源码 mistake@pwnable:~$ ls flag mi ...
- 通过STC15F2K60S2控制SIM900A发中英文短信,打电话
本文通过串口通信,使用STC15系列单片机实现发短信打电话功能. 一. 注意事项 1. 首先要确定手机卡已经注册到网络,具备打电话发短信功能 2. 正确的硬件连接: P3.0-----STXD或者5V ...
- 一个有关 scala 编程语言 的博客
http://www.cnblogs.com/superjt/category/312683.html
- 2019-07-31【机器学习】无监督学习之降维NMF算法 (人脸特征提取)
代码 from numpy.random import RandomState #加载RandomState用于创建随机种子 import matplotlib.pyplot as plt from ...
- C# windows服务没有RunInstallerAttribute.Yes的公共安装程序
1.在视图状态 右键添加ServiceInstaller及ServiceProcessInstaller两个控件; 2.将serviceProcessInstaller类的Account属性改为 Lo ...
- stand up meeting 11/23/2015
组员 周末工作 工作耗时/h 明日计划 计划耗时/h 冯晓云 完成网络状况的侦听,对网络连接断开,WiFi状况不佳,未查询到结果设定不同的返回码,按约定格式返回:对于超时未查询进行了相关的学习: 3 ...