首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

在业务中砰然坠地的设计

  • 25-04-20 21:00
  • 4237
  • 9683
juejin.cn

热乎的夏天到了,硕士毕业已经 4 年,21 年的阿布,还在为了华为的 offer 努力的刷着慕课(虽然最后也没去),学习一条条的设计模式,单例、工厂、责任链、策略 等等。等草草的工作了这几年发现,课程上面优雅新奇不起眼的设计模式,与实际的业务场景结合起来,在工作中 砰然坠地 之后,有的是非常普通的代码,有的是了不起的、让人印象深刻的设计。

在中国,任何超脱飞扬的思想都会砰然坠地的,现实的引力太沉重了。

资源加载厂

当一条链路里面,涉及到 Rpc、Redis、特征、实验 等一系列资源调用,而且,这些资源调用都是固定的,即资源调用没有前置条件,只与调用的场景相关,你会怎么做呢?阿布当时是新建了一个统一资源模块,接口类有两个方法,getResource() 为资源获取,getScene() 为资源标识,实现该接口的为几个抽象模板类。

  • IResource
    • AbstractFeatureResource
      • FeedbackEventFeatureResource

当需要把统一资源加载模块提供出去的时候,第一种方式是把接口提供出去,如:

java
代码解读
复制代码
Map sceneResources = new HashMap<>();

调用方需要根据当前场景获取映射的资源标识,通过资源标识获取资源类,然后通过 getResource() 方法加载资源,如果一条链路里面需要多次调用资源,那就需要多次的执行上述动作。
更为简单的是,提供一个通用的资源加载类以及资源加载方法,如:

java
代码解读
复制代码
public class ResouceLoader { Map sceneResources = new HashMap<>(); public ResourceResult load(ResourceContext context, String scene) { // todo } }

方法内部封装获取资源标识、获取并解析资源的过程,调用方通过 ResouceLoader#load 方法就可以获取到本场景对应的资源结果,当然,作为一个稳定的资源模块,方法内部封装的打点、监控、降级也必不可少。

这就是工厂的能力,它内聚了全部的资源生产线,并提供通用的结果生产能力,让外部可以更加简单的完成调用。但笔者也想说,不是任何的接口都需要创建一个工厂,大多数场景下,直接把一系列的接口注入到调用方更为简单合适,有时候,减少不必要类的数量也很重要。

责任链与策略的选择

过滤,在实际的业务中非常常见,拿到一堆的商品,通过一些属性进行过滤,得到符合的商品,或者是拿到一堆的用户,通过用户的特征进行过滤,得到符合的用户。如果让你来进行过滤模块的设计,你会怎么做,会使用责任链还是策略,使用策略模式的过滤很简单,组合并执行 doFilter 过滤方法,使用责任链的 append and next 会很酷。

如果使用责任链模式,接口会这样设计:

java
代码解读
复制代码
public Interface IFilter { boolean doFilter(FilterContext context); IFilter next(); }

通过实现 doFilter 方法以及链式调用的 next 方法,类似于组装了一个链条,调用时,执行入口的过滤类,然后获取下一个过滤类,继续执行,在过滤结果为 true 的时候或者 next == null 时,责任链执行完成。

使用策略模式的接口会是这样:

java
代码解读
复制代码
public Interface IFilter { boolean doFilter(FilterContext context); }

调用时,拿到实现接口类的所有需要执行的过滤类集合,遍历集合并执行过滤。

在实际的业务中,阿布见到的绝大多数的过滤场景都是使用策略模式实现的,这种方式更为简单,可读性高。在偶尔的看到责任链实现的代码时,笔者也总是会考虑,使用策略模式是不是更加简单易懂,很多场景下,这两种模式只有形式上的差别,实际的执行逻辑是相同的。

工程里面的 facade

门面模式的概念实在是太宽泛了,在很多项目中,都会定义一个 facade 模块,这个模块就是服务对外暴露的接口模块,一个服务的门面就是它所提供的接口。

一个服务如此,服务里面的模块,模块里面的方法也是如此,当你考虑实现一个功能时,首先考虑的是怎么定义一个接口,怎么定义接口的入参、结果、方法名,这个过程就是搭建门面的过程。

联动的开关

有这样一个项目,需要你设计一个总的开关,三个子开关,子开关有 微信通知开关、短信通知开关、端内通知开关(当前应用的通知开关),其中打开任意子开关,总开关会联动打开;打开总开关,上次的子开关会联动打开;打开微信或者短信开关,端内开关会联动打开。

最直观的设计当然是,提供每个开关开启的接口。例如短信开关开启的接口,打开短信开关,联动打开总开关,再联动打开上次打开过的子开关,再打开端内开关。

java
代码解读
复制代码
public void openMsgSwitch() { // 1.打开总开关 this.openMainSwitch(); // 2.打开上次打开过的开关 this.openLastSwitch(); // 3.打开端内开关 this.openAppSwitch(); }

很复杂,而且这么多开关,我们需要提供非常多的接口,如果加上开关的关闭事件,就更加复杂了。

如果我们换一种思路,引入观察者模式的思想,每个子开关都订阅总开关的打开事件,端内开关订阅所有开关的打开事件,总开关订阅子开关的打开事件。

当短信开关开启,发生了变更,首先总开关收到订阅事件,总开关开启,然后各个子开关收到总开关的订阅事件,判断自己是否为上次打开的开关,如果是则打开,端内开关收到了其它开关开启的事件,直接开启。

这种思路是不是非常简单,可读性好,易于扩展,当后续新增一个开关时,只需要将该开关订阅相应的事件,并修改关联开关的订阅方法,就可以完成新开关的增加。

待续

阿布想到哪儿就记到哪儿,实际业务中设计模式的应用当然不止这些,也并非阿布写的这么简单,就比如刚说的开关,实际业务中是 2 个大开关,5 个子开关,交互的逻辑非常复杂,但内部处理的核心就是观察这种思想,把视角反转一下,程序的设计真的很有趣。

希望大家也能给阿布补充并指正,感谢!

注:本文转载自juejin.cn的起风了布布的文章"https://juejin.cn/post/7494695992877809698"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2492) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

103
后端
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2025 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top