带你读《2022技术人的百宝黑皮书》——谈一谈凑单页的那些优雅设计(3)https://developer.aliyun.com/article/1338379?groupCode=taobaotech
该方案可以清晰看到整个主流程的分流结构,但会使得主流程不够整洁,降低可读性,很多人都习惯把该判断写到各自的方法里如下。(当然也有人每个模块都单独写一个主流程,以上只是为了文章易懂简化了代码,实际主流程较长,并且大部分都是需要处理的,如果每个模块都单独自己创建主流程,会带来很多重复代码,不推荐)
private void buildAtmosphere(ItemShow itemShow, Map<String, String> map) { if (Objects.equals(soluction, FiltrateFeedsSolution.class)) { return; } GuideInfoDTO guideInfoDTO = new GuideInfoDTO(); AtmosphereResult<Map<Long, List<AtmosphereFullDTO>>> atmosphereResult = guideAtmo- sphereClient .extract(guideInfoDTO, "gather", "item"); List<IconText> iconTexts = parseAtmosphere(atmosphereResult); itemShow.setItemBenefits(iconTexts); 10 }
纵观整个凑单的业务逻辑,不管是参数组装,商品组装,购物车组装,榜单组装,都需要信息组装的能力,并且他们都有如下的特性:
- 每个或每几个字段的组装都不影响其他字段,就算出现异常也不应该影响其他字段的拼装
- 在消费者链路下,性能的要求会比较高,能不用访问的组装逻辑就不去访问,能不调用下游,就不去调用下游
- 如果在组装的过程中发现有写字段是必须要的,但没有补全,则提前终止流程
- 每个方法的处理需要记录耗时,开发能清楚的知道耗时在哪些地方,方便找到需要优化的代码
以上的点都很小,不做或者单独做都不影响整体,凑单页含有这么多组装逻辑的情况下,如果以上逻辑全部都写一遍,将产生大量的冗余代码。但对自己代码要求比较高的人来说,这些点不加上去,心里总感觉有根刺在。慢慢的就会因为自己之前设计考虑的不全,打各种补丁,就好比想知道某个方法的耗时,就会写如下代码:
long startTime = System.currentTimeMillis(); // 主要处理 buildAtmosphere(itemShow, summaryMap); long endTime = System.currentTimeMillis(); return endTime - startTime;
凑单各域都是做此类型的组装,有商品组装,参数组装,榜单组装,购物车组装。针对凑单业务的特性,寻遍各类设计模式,最终选择了责任链 + 命令模式。
在 GoF 的《设计模式》中,责任链模式是这么定义的:
将请求的发送和接收解耦,让多个接收对象都有机会处理这个请求。将这些接收对象串成一条链,并沿着这条链传递这个请求,
直到链上的某个接收对象能够处理它为止。
首先,我们来看,职责链模式如何应对代码的复杂性。
将大块代码逻辑拆分成函数,将大类拆分成小类,是应对代码复杂性的常用方法。应用职责链模式,我们把各个商品组装继续拆分出来,设计成独立的类,进一步简化了商品组装类,让类的代码不会过多,过复杂。
其次,我们再来看,职责链模式如何让代码满足开闭原则,提高代码的扩展性。
当我们要扩展新的组装逻辑的时候,比如,我们还需要增加价格隐藏过滤,按照非职责链模式的代码实现方式,我们需要修改主类的代码,违反开闭原则。不过,这样的修改还算比较集中,也是可以接受的。而职责链模式的实现方式更加优雅,只需要新添加一个Command 类(实际处理类采用了命令模式做一些业务定制的扩展),并且通过addCommand() 函数将它添加到 Chain 中即可,其他代码完全不需要修改。
接下来就是使用该模式,对凑单全域进行改造升级,核心架构图如下
带你读《2022技术人的百宝黑皮书》——谈一谈凑单页的那些优雅设计(5)https://developer.aliyun.com/article/1338377?groupCode=taobaotech