当前位置:网站首页>梁老师小课堂|谈谈模板方法模式
梁老师小课堂|谈谈模板方法模式
2020-11-08 23:53:00 【公众号_松华说】
众多设计模式中,我觉得模板方法模式是很好理解,也很值得深入研究的技巧。定义如下,在一个包含多个步骤的业务框架中,大部分步骤是固定不变,并且适用于多种业务场景,可变的步骤则留给子类独立实现,从而分离了稳定和变化。
使用这种模式稍不留心,就会出现一些奇奇怪怪的问题。第一个是多个抽象方法会修改相同的变量,方法间出现强关联,第二个问题是定义了过多的抽象方法。后者正是今天想和你聊的话题,跟着我的步伐往下看吧。
一、为什么会出现这种问题?
我认为是这样的,产品经理从业务角度告诉我们,这个功能涉及到哪些步骤,每个步骤需要完成哪些事,然后我们就照搬概念将其转换成代码,考虑到有些步骤会涉及到多个实现,于是留了很多扩展方法。
不久后,新的业务需要复用这些流程,需要步骤1\2\3,但是不需要步骤4\5,甚至看不懂步骤4\5是做什么的,也不知道什么条件下会被调用,原有设计就显得不够简单了。
怎么理解这里说的简单呢?简单是站在人的角度来看的。假如,定义者和实现者来自两个不同的团队,实现者阅读文档后还需要定义者解释,才知道怎样实现抽象方法是正确的,那它就是复杂的。这个是我的真实感受,之前我在做中台通用能力建设,通过扩展点对外赋能时,思考最多的就是如何让第三方快速理解并上手。
总结一下,生搬硬套需求文档,让执行顺序完整地反映在代码结构中,会导致模板方法模式出现了过多的抽象方法。
二、出现了怎么办?
出现了过多的抽象方法怎么办呢?其实我们可以利用接口适配器模式来打补丁。
实际做法是这样的,创建一个抽象类Wrapper,实现所有的方法,方法实现不需要具体业务含义。当我们编写具体实现类时,继承Wrapper类,重写它自己关心的方法,这样就不用实现不了解的步骤了。
使用接口适配器来兼容可能还不够,考虑这样的情况,模板中的抽象方法明确需要有返回值,要怎么处理呢?
看来只好继续打补丁了。比如,定义一些默认值,业务流程中对这些值进行抛弃处理。或者,方法默认实现运行时抛出异常,表明不支持该操作,必须有第三方实现才行。这两个方案其实都不好。第一种有特殊逻辑,估计会被很多人鄙视。第二种方案相对优雅一些,缺点是调试过程才能发现异常。
总结一下,使用接口适配器模式,让子类只关心它需要的方法,这样就把旧代码、脏代码盘活了。
三、如何避免出现过多的抽象方法?
模板方法模式出现过多的抽象方法,侧面说明了流程步骤繁杂,不够简单。所以,这个问题的另外一种描述是,模板方法设计时如何避免暴露过多的细节。
我的建议是,对业务逻辑进行整理,把同类行为进行提取,或者把共享很多信息的方法合并,用一个通用的术语来概括这个环节,把细节隐藏起来,再用组合的方式加载进来,不要把代码直接平铺。
举例说明一下。在一个请求链路中,中间方法通过缓存客户端直接控制缓存的清除、缓存值的设置,其他链路则读取缓存值。这种编码风格,会把缓存Key、缓存组件暴露给第三方,导致后续修改困难。正常应该新建一个业务类,专门与该缓存Key打交道。
总结一下,避免出现过多的抽象方法的关键是如何避免暴露过多的细节。
本文分享自微信公众号 - 松华说(songhuasay)。
如有侵权,请联系 [email protected] 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。
版权声明
本文为[公众号_松华说]所创,转载请带上原文链接,感谢
https://my.oschina.net/liangsonghua/blog/4708396
边栏推荐
- 老大问我:“建表为啥还设置个自增 id ?用流水号当主键不正好么?”
- The interface testing tool eolinker makes post request
- API生命周期的5个阶段
- Decorator (1)
- Esockettimeout solution in request in nodejs
- 通过canvas获取视频第一帧封面图
- 寻找性能更优秀的不可变小字典
- 都说程序员钱多空少,程序员真的忙到没时间回信息了吗?
- Come and have a look! What is the relationship between AQS and countdownlatch?
- 综合架构的简述
猜你喜欢
使用递增计数器的线程同步工具 —— 信号量,它的原理是什么样子的?
MYCAT build
Solve the problem that the value of new date() of JS in IE and Firefox is invalid date and Nan Nan
单例模式的五种设计方案
Five phases of API life cycle
基于链表的有界阻塞队列 —— LinkedBlockingQueue
Introduction skills of big data software learning
接口测试工具Eolinker进行post请求
JVM Zhenxiang series: easy understanding of class files to virtual machines (Part 2)
Realization of file copy
随机推荐
实验一作业
LeetCode 45 跳跃游戏II
大数据岗位基础要求有哪些?
快来看看!AQS 和 CountDownLatch 有怎么样的关系?
第一部分——第2章指针操作
VIM 入门手册, (VS Code)
Newbe.ObjectVisitor 样例 1
Fiddler can't grab requests from browsers like Google_ Solution
JVM真香系列:轻松理解class文件到虚拟机(下)
寻找性能更优秀的不可变小字典
使用容器存储表格数据
国内三大云数据库测试对比
你有没有想过为什么交易和退款要拆开不同的表
On buffer overflow
代码保存
APReLU:跨界应用,用于机器故障检测的自适应ReLU | IEEE TIE 2020
STC转STM32第一次开发
VIM Introduction Manual, (vs Code)
Programmers should know the URI, a comprehensive understanding of the article
文件拷贝的实现