梁老师小课堂|谈谈模板方法模式

|▌冷眼眸甩不掉的悲伤 提交于 2020-12-25 05:54:49

众多设计模式中,我觉得模板方法模式是很好理解,也很值得深入研究的技巧。定义如下,在一个包含多个步骤的业务框架中,大部分步骤是固定不变,并且适用于多种业务场景,可变的步骤则留给子类独立实现,从而分离了稳定和变化。


使用这种模式稍不留心,就会出现一些奇奇怪怪的问题。第一个是多个抽象方法会修改相同的变量,方法间出现强关联,第二个问题是定义了过多的抽象方法。后者正是今天想和你聊的话题,跟着我的步伐往下看吧。


一、为什么会出现这种问题?


我认为是这样的,产品经理从业务角度告诉我们,这个功能涉及到哪些步骤,每个步骤需要完成哪些事,然后我们就照搬概念将其转换成代码,考虑到有些步骤会涉及到多个实现,于是留了很多扩展方法。


不久后,新的业务需要复用这些流程,需要步骤1\2\3,但是不需要步骤4\5,甚至看不懂步骤4\5是做什么的,也不知道什么条件下会被调用,原有设计就显得不够简单了。


怎么理解这里说的简单呢?简单是站在人的角度来看的。假如,定义者和实现者来自两个不同的团队,实现者阅读文档后还需要定义者解释,才知道怎样实现抽象方法是正确的,那它就是复杂的。这个是我的真实感受,之前我在做中台通用能力建设,通过扩展点对外赋能时,思考最多的就是如何让第三方快速理解并上手。


总结一下,生搬硬套需求文档,让执行顺序完整地反映在代码结构中,会导致模板方法模式出现了过多的抽象方法。


二、出现了怎么办?


出现了过多的抽象方法怎么办呢?其实我们可以利用接口适配器模式来打补丁。


实际做法是这样的,创建一个抽象类Wrapper,实现所有的方法,方法实现不需要具体业务含义。当我们编写具体实现类时,继承Wrapper类,重写它自己关心的方法,这样就不用实现不了解的步骤了。


使用接口适配器来兼容可能还不够,考虑这样的情况,模板中的抽象方法明确需要有返回值,要怎么处理呢?


看来只好继续打补丁了。比如,定义一些默认值,业务流程中对这些值进行抛弃处理。或者,方法默认实现运行时抛出异常,表明不支持该操作,必须有第三方实现才行。这两个方案其实都不好。第一种有特殊逻辑,估计会被很多人鄙视。第二种方案相对优雅一些,缺点是调试过程才能发现异常。


总结一下,使用接口适配器模式,让子类只关心它需要的方法,这样就把旧代码、脏代码盘活了。


三、如何避免出现过多的抽象方法?


模板方法模式出现过多的抽象方法,侧面说明了流程步骤繁杂,不够简单。所以,这个问题的另外一种描述是,模板方法设计时如何避免暴露过多的细节。


我的建议是,对业务逻辑进行整理,把同类行为进行提取,或者把共享很多信息的方法合并,用一个通用的术语来概括这个环节,把细节隐藏起来,再用组合的方式加载进来,不要把代码直接平铺。


举例说明一下。在一个请求链路中,中间方法通过缓存客户端直接控制缓存的清除、缓存值的设置,其他链路则读取缓存值。这种编码风格,会把缓存Key、缓存组件暴露给第三方,导致后续修改困难。正常应该新建一个业务类,专门与该缓存Key打交道。


总结一下,避免出现过多的抽象方法的关键是如何避免暴露过多的细节。

本文分享自微信公众号 - 松华说(songhuasay)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!