模板方法 (宝,我输液了,输的想你的夜)
微信搜索【三太子敖丙】关注这个技术不咋地,面试还行的程序员。
本文 GitHub https://github.com/JavaFamily 已收录,有一线大厂面试完整考点、资料以及我的系列文章。
大家每到一家公司都会发现,每个公司都会有一个规范,比如说请假流程规范,代码规范等等。每个公司都有这个流程,只是里面的具体执行条件不一样而已。
在设计模式中的模版方法模式,也是可以理解为一种规范模版。主要是提升我们代码的复用性,以及扩展等问题。
这样的模板方法在我们当舔狗跟妹妹们聊天的时候也是可以用到的,比如这样一个模板:
“宝,XXXX了,XXXX什么XX?X你的XXX”
当我拿到这样一个模板的时候,我就可以举一反三直接套用了,我们直接填参数就可以了,比如:
“宝,我打疫苗了,打的什么苗 ,爱你的每一秒 ”
“宝,我做核酸了,做的什么酸,得不到你的心酸”
“宝,今天去输液了,输的什么液,想你的夜”
…
好了言归正传,在框架中模版方法模式也是很常见的。
今天就具体来聊聊设计模式中行为型设计模式中模版方法模式。
设计模式系列往期文章:
- 单例模式
- 工厂模式
- 流程引擎
- 建造者模式
- 原型模式
- 责任链模式
- 观察者模式
- 策略模式
大纲
还是老规矩从上图五个方面来分别具体和大家聊聊模版方法模式
定义
模版方法模式的定义以及目的?
定义:模板方法模式在一个方法中定义一个算法骨架,并将某些步骤推迟到子类中实现。模板方法模式可以让子类在不改变算法整体结构的情况下,重新定义算法中的某些步骤
目的:1.使用模版方法模式的目的是避免编写重复代码,以便开发人员可以专注于核心业务逻辑的实现
2.解决接口与接口实现类之间继承矛盾问题
以上定义来自《设计模式之美》
结构图:
- AbstractTemplate(抽象模版):定义一系列抽象方法,或者实现的方法,又或者是钩子方法。即:定义流程
- ConcreteTemplate(具体模版):实现父类抽象方法,基于本身不同的模版业务逻辑,实现不同的业务逻辑代码。即:抽象方法实现相同,内部逻辑不同
整个结构图看起来还是很简单的,但是还是要理解设计模式解决什么问题。
代码实现?还是举例吧。
还是以上面的请假举例吧,假设现在A公司请假需要直属领导审批以及通知HR有人请假了就可以了,B公司需要直属领导,部门负责人审批最后通知HR,方能完成整个请假流程。那作为OA办公流程怎么去处理这个问题嘛?直接看代码实现吧!
public abstract class AskForLeaveFlow {// 一级组长直接审批protected abstract void firstGroupLeader(String name);// 二级组长部门负责人审批protected void secondGroupLeader(String name) {}// 告知HR有人请假了private final void notifyHr(String name) {System.out.println("当前有人请假了,请假人:" + name);}// 请假流模版public void askForLeave(String name) {firstGroupLeader(name);secondGroupLeader(name);notifyHr(name);}}
首先还是定义一个请假流程,其中:
firstGroupLeader方法为abstract修饰,则作为子类都是必须要实现的
secondGroupLeader 二级领导审批,在子类中可以重写,也可不重写
notifyHr 方法为通知HR,已经内部实现
最后一个askForLeave请假流程方法,把以上模版方法串起来
public class CompanyA extends AskForLeaveFlow {@Overrideprotected void firstGroupLeader(String name) {System.out.println("CompanyA 组内有人请假,请假人:" + name);}
}public class CompanyB extends AskForLeaveFlow {@Overrideprotected void firstGroupLeader(String name) {System.out.println("CompanyB 组内有人请假,请假人:" + name);}@Overrideprotected void secondGroupLeader(String name){System.out.println("CompanyB 部门有人请假,请假人:" + name);}
}
在CompanyA以及CompanyB中,secondGroupLeader二级领导可以选择重写或者不重写,这个类模版方法简称为钩子方法。
public class testTemplate {public static void main(String[] args) {// 公司A请假流程模版AskForLeaveFlow companyA = new CompanyA();companyA.askForLeave("敖丙");// 结果:CompanyA 组内有人请假,请假人:敖丙// 当前有人请假了,请假人:敖丙AskForLeaveFlow companyB = new CompanyB();companyB.askForLeave("敖丙");// 结果:CompanyB 组内有人请假,请假人:敖丙// CompanyB 部门有人请假,请假人:敖丙// 当前有人请假了,请假人:敖丙}
}
最后就是看测试dome结果了。companyA和companyB分别输出了对应的请假流程。
细心的同学可能已经发现了,做为模版方法中里面除了可以有抽象方法外,还可以有具体的实现方法以及钩子方法。
所以大家在应用的过程可以多考虑考虑在内部定义模版方法时,应该定义成抽象方法还是其它的。
框架中的应用
模版方法模式在我们常见的Java的框架中也是非常常见的,只是可能我们平时没有注意到这一点而已。
第一个:首先我们学SpringMVC的时候,最开始都会写一些Servlet来作为处理一些post或者get请求等。
这里直接看这个源码大家就可以发现这也是直接使用模版方法模式的思想,期间在HttpServlet 继承GenericServlet中也还是模版方法的体现,这说明了可以多次抽象构建模版。
第二个:常见问的文件流中,Java IO 类中的InputStream、OutputStream、Reader、Writer等都能看到模版方法模式的身影。
上面是我贴出的部分InputStream的源码,主要看这个read模版方法,也就是模版方法模式的体现。
当然IO类中还有很多其他的,我就不一一贴源码出来了,感情兴趣的同学,可以自己打开源码了解了解。
业务举例
在业务中怎么使用模版方法?
首先需要理解模版方法它是为了增加代码的复用性,以及扩展性而存在的,所以本着这个思想我还是给大家举一个例子吧。
之前写责任链模式最后给大家举例商品详情,这次还是用商品详情,但是用模版方法模式来实现这个问题,理解为商详2.0版本。
商品详情展示我们可以是分模块展示的,比如头图,商品信息,sku信息,配送地址,分期付费等等。
那么怎么进行组装到商品详情的展示呢?
流程图:
可以看到一个请求过来,可以有模块组装器选择组装返回结果。
提一个点,在第二步请求的模块的时候为了减少整个链路的请求时间可以考虑是串行,或者并行(开线程池处理)。
接下来直接看代码吧
public abstract class AbstractTemplateBlock<T> {// 组装结果public T template(ModelContainer modelContainer) {T block = initBlock();try {this.doWork(modelContainer, block);} catch (Exception e) {// 可以选择捕获异常,是中断流程,还是只打印日志,不中断流程}return block;}// 初始化构建返回结果模型protected abstract T initBlock();// 定义抽象模版protected abstract void doWork(ModelContainer modelContainer, T block) throws Exception;
}
还是先创建模版Block
@Component
public class ItemInfoBlock extends AbstractTemplateBlock<ItemInfoBlock.ItemInfo> {@Overrideprotected ItemInfoBlock.ItemInfo initBlock() {return new ItemInfoBlock.ItemInfo();}// 模拟业务逻辑,组装返回商品信息模块数据@Overrideprotected void doWork(ModelContainer modelContainer, ItemInfo block) throws Exception {block.setItemId(123L);block.setItemName("测试");}@Datapublic static class ItemInfo {private Long itemId;private String itemName;}
}
这里只写了一个ItemInfoBlock,其他的模块也是这一样的写法,所以就不全写出来了。
public static void main(String[] args) {// 1.模拟获取SpringBeanApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");ItemInfoBlock itemInfoBlock = (ItemInfoBlock) applicationContext.getBean("itemInfoBlock");// 2. ModelContainer可以理解为贯穿上下文中的请求参数,或者一些组装数据需要的预加载数据ModelContainer modelContainer = new ModelContainer();// 3. 获取返回结果ItemInfoBlock.ItemInfo itemInfo = itemInfoBlock.template(modelContainer);System.out.println(JSON.toJSONString(itemInfo));// 结果:{"itemId":123,"itemName":"测试"}}
最后就是看测试demo了,可以看到再每一个模块中都是有一个AbstractTemplateBlock,内部包含doWork抽象方法,由子类去实现当前自己的业务逻辑。
同时第三步获取返回结果时,我只是单独列出来,大家可以根据实际情况还能做改造。比如说返回map结构等 mapKey 是模块名称,value是数据。
当前这种组装商品详情的模式也是比较常见的一种方式。代码的复用性高,同时扩展性也有一定的体现,符合模版方法模式的思想。
总结
模版方法模式的特点大家应该也能体会到了,适用场景还是为了增加代码的复用性,以及扩展性。
还是那句话存在即合理,不要因设计模式而在写代码时强行嵌套。合理的学习每种设计模式适合场景,解决什么问题。
宝,明天我可能无法正常更新了,我生病了在输液。
敖丙把自己的面试文章整理成了一本电子书,共 1630页!
干货满满,字字精髓。目录如下,还有我复习时总结的面试题以及简历模板,现在免费送给大家。
链接:https://pan.baidu.com/s/1ZQEKJBgtYle3v-1LimcSwg 密码:wjk6
我是敖丙,你知道的越多,你不知道的越多,感谢各位人才的:点赞、收藏和评论,我们下期见!
文章持续更新,可以微信搜一搜「 三太子敖丙 」第一时间阅读,回复【资料】有我准备的一线大厂面试资料和简历模板,本文 GitHub https://github.com/JavaFamily 已经收录,有大厂面试完整考点,欢迎Star。
模板方法 (宝,我输液了,输的想你的夜)相关推荐
- 黄聪:淘宝用户在宝贝详情页想看到什么
下载地址:淘宝用户在宝贝详情页想看到什么_(1).pdf
- 淘宝现金红包系统 都是你们想要的!
这个支付方式我想很多人都想要的 对吧 我们是专门做支付行业的 做的也都是你们需要的东西 比如说 淘宝现金红包 支付宝H5 三网话费支付系统 联通卡密 咸鱼代付 钉钉红包 钉钉代付 支付宝网关 协议版本 ...
- 用Python爬取淘宝1000多商品,只想为老父亲做点事
本文来自我们小密圈的一位非常铁杆的粉丝,这位粉丝看我的文章大概有2年多了,非常朴实的一位铁杆,希望大家耐心看完这篇文章! 北靠黄河南靠山,我家住在老潼关. 对,就是那个鸡鸣啼三省(秦晋豫)的陕西东大门 ...
- DB2分页SQL优化(宝,我优化了分页,每分钟都想你的夜)
前言: 最近,项目中的一个 DB2分页查询很慢 ,组长将此分页的优化分派给了我:然后一顿优化(乱操作)后,将DB2分页查询耗时降到了比较满意的情况,[ 开森 ]: 然后马上将结果报告了组长,组长查看我 ...
- 张一鸣这一条微博,阿里P8的我,竟然想了一夜
"很多人之所以能成功,就是选择了那条更难的路." 是的,我选了. 可我现在正躲在卫生间里哭. 我老婆在外面嘶吼着,"你一个大男人,躲起来算怎么回事啊!有本事你别创业了,现 ...
- 想念你的夜,一个人流泪,两颗心体会
夜色朦胧,月儿弯如勾,风又吹起,泪眼迷离,深深的想,狠狠的念,借天边弯弯的小船,伴着夜色,载着思念,摆渡到你心灵的彼岸. 柔情似水,似水柔情,再美的词语,也诠释不了你的那份温柔. 繁星点点,点点繁星, ...
- 想你的夜,爱与痛在我心里纠缠
曾经在我心里无数次幻想,再去看看你,再摸摸你的脸,再看看你的眼睛,你过得还好吗? 当我从这座城市爬山涉水去到有你的地方,站在你面前看着你从我身旁走过,却没认出我是谁..我想,我会痛得只剩泪流满面.于是 ...
- 蝉妈妈发布孙一宁抖音直播数据:“想你的夜”涨粉200万
近日,网红主播孙一宁与王思聪曝出情感纠纷,在网络上掀起骂战,而在热度还没褪去之际,这场风波的女主角孙一宁在抖音高调开播. 6月16日晚上,孙一宁顶着 "iiiis"这个ID现身在抖 ...
- 【无标题】自己也DIY充电宝,带照明功能的。
事情还的从十几年前说起,当时还不太流行锂电池的电动车,我从网上购买了二手的锂电池用于自己的电动车,结果不太行,续航里程特别少没办法就搁置了.晒图购买的电池. 快10年了电池还能有多大容量得打个问号 好 ...
- 《淘宝店铺经营管理一册通》一一1.3 页面中的图片应用
本节书摘来自异步社区出版社<淘宝店铺经营管理一册通>一书中的第1章,第1.3节,作者: 葛存山,更多章节内容可以访问云栖社区"异步社区"公众号查看. 1.3 页面中的图 ...
最新文章
- 这所211大学,实力强悍,适合“踩线生”报考!
- 大数据营销的7个雷区,千万别中招
- python语言编程中的保留字_Python语言程序设计整理
- 查看oracle连接客户端
- 三星的S3C2440A 存储器控制器
- 最大连续子数组和 动态规划_53. 最大子序和(动态规划)
- cocos tiledmap无法显示 不显示 无法加载
- 计算机组装方案i5,3000元预算方案i5 8400/GTX1050Ti装配配置清单推荐
- 信创-东方通和达梦适配
- Tuning (调试)
- 安装tensorflow
- java仙侠回合制单机游戏_2019回合仙侠手游排行榜 好玩的回合制单机仙侠手游推荐...
- 【计算机网络】网络命令的使用
- “鲜花插在牛粪上” 好域名嫁错郎?
- c语言循环码编码,二进制与循环码各有何特点
- HP-UX培训学习笔记
- 图解LeetCode——1184. 公交站间的距离(难度:简单)
- Android知识点及资料汇总(不断更新中)
- 【软件】Windows 公文包 功能 U盘同步篇
- python的代码保存到文档中 打不开怎么办_py文件打不开怎么办?
热门文章
- Win10 开机system进程占用CPU 20%,ACPI.sys hardware interrupt
- DDos攻击防御策略
- matlab 水文断面,基于MATLAB的河道横断面的绘制
- push代码至gitee码云报错unable to access ‘https://gitee.com/*/git/‘: The requested URL returned error: 403
- 怎么样绘制简易地图,如何制作一个电子地图?
- Slf4j+logback实现日志打印-获取调用者类及方法行数信息
- 数学分析(1):集合相关公式的证明
- 流量卡之家:物联网僵尸网络和DDoS攻击:构建网络风险防火墙
- Java中ElasticSearch的各种查询(普通,模糊,前缀,高亮,聚合,范围)
- linux中运行alise,Linux学习笔记