以订单退款流程为例,聊聊如何优化策略模式

news2024/11/29 2:54:22

如果有人问你什么是策略模式?你可以尝试这样回答

策略模式是一种行为设计模式,它允许在运行时根据不同的情况选择不同的算法策略。这种模式将算法的定义与使用的代码分离开来,使得代码更加可读、可维护和可扩展。

在策略模式中,通常有一个抽象的策略接口,定义了一系列可以被不同策略实现类所实现的方法。在使用时,可以根据需要选择合适的具体策略类,并通过接口进行调用。

虽然解释了策略模式,但是面试官可能会认为你在吊书袋,完全没有自己的理解。我因为被领导卷到了,所以对策略模式有一些其他的理解,接下来我从业务中台实际遇到的问题出发,谈谈怎么被领导卷到,谈谈我对策略模式的优化和理解。

在业务中台,可以根据具体情况选择合适的策略类来执行相应的业务逻辑,从而满足不同业务方的要求。

由于各个业务方的业务逻辑存在差异性和相似性,编写中台代码时需要考虑这些差异性,并预留扩展点以供不同业务方根据自身需求提供策略类。在这种情况下,可以应用策略模式。

7eba8d5f2111083b5594ddc7161fe50c.jpeg

当业务方有特殊的业务逻辑时,只需要添加新的策略实现类即可,不需要修改现有的代码,方便了后续的维护和扩展。

然而在我们在应用策略模式时遇到了几个问题

遇到的实际问题

由于业务中台逻辑非常复杂,每个业务线的业务场景都很难保证完全一样,在代码实践中我们的系统出现了非常庞大复杂的策略类,将大量业务逻辑整合到同一个策略中,这导致系统能力复用非常困难。

举个例子,在退款校验逻辑中 业务场景 A,(售卖红包,类似于美团饿了么会员)。 需要判断如下校验逻辑,如果命中,则不允许退款!

  1. 订单是否在生效期,过期不允许退

  2. 订单是否在已使用,已使用不可退

  3. 订单如果是某类特殊商品订单,则不可退

  4. 如果超过当天最大退款次数,则不可退。

于是我们在编写代码时,就新定义 ConcreteStrategyA ,将以上 4 个业务逻辑放到策略类中。

过一段时间,又出现了业务场景 B(售卖红包,类似于美团饿了么会员)。它的校验逻辑和A 大同小异

  1. 订单是否在生效期,过期不允许退

  2. 订单售卖的红包完全使用不可退,部分使用可以退。

  3. 如果超过当天最大退款次数,则不可退。

业务场景B 相比A 而言,少校验了 “特殊商品订单不可退”的逻辑,同时增加了部分使用可以退的逻辑。

如何设计代码实现两种业务场景的校验逻辑呢? 这是非常具体的问题,如果是你如何实现呢?

完全独立的策略类

我们在最开始写代码时,分别独立实现了 ConcreteStrategyA、ConcreteStrategyB。两者的校验逻辑各自独立,没有代码复用。

此时的系统类图如下

bca388b220251a2904f32ec00c8f9697.jpeg

这种实现方式是大量的代码拷贝,例如退款次数限制、生效期校验等代码都大量重复拷贝了。

后来我们发现了这个问题,将相关校验方法抽到父类中。

继承共同的父类

为了更好的复用校验策略,我们将校验生效期的方法、校验退款次数的方法抽取到共同的父级策略类。由具体的子策略类继承BaseStrategy 父策略类,在校验逻辑中,使用父级的校验方法。

如下图的类图所示 cf11d7aafd67f04e84ea231e7761797e.jpeg

在相当长的一段时间里,我们认为这已经是最优的实现方式了。

但是被领导卷到了!

26b4053c14b5530e5eaba4bfdb1ed89d.jpeg

被卷到了

“新增业务场景时,为什么校验逻辑都是复用的原有能力,还需要新增扩展类,还需要开发代码呢?” 领导这样问道。

我尝试回答领导的问题:“开发这段代码,并不算太难,只需要增加一个扩展类就可以了!”

“你数数现在有多少个扩展类了?” 领导似乎有些生气,

我一看扩展类的数量,被吓到了,已经有了15个扩展类。这一刻真的非常尴尬,平时领导从不亲自看代码。估计是突然心血来潮。从表情来看,他好像很生气,估计是代码没看懂!

“我看到这部分代码时,想要查看具体的策略类,但Idea直接刷出了15个策略类……为什么会有这么多的扩展类呢?” 领导进一步补充道。

场面僵住了,我也没什么好办法……。当然领导向来的传统是:只提问题,不给解决办法! 我只能自己想解决办法!如何解决策略类过多、扩展类膨胀的问题呢?

42b7f866f5f7b19cbd54cd1bb669fd86.jpeg

策略类过多怎么办!

当业务场景非常多,业务逻辑非常复杂时,确实会出现非常多的策略类。但领导的问题是,现有业务场景有很多相似性,某些新增业务场景和原有业务场景类似,校验逻辑也是类似的,为什么还需要新增扩展类呢?

经过深思熟虑,让我发现问题所在!

策略类粒度太粗,导致系统复用难

目前我们的系统设计是每个业务场景都有单独的策略,这是大多数人认可的做法。不同的业务场景需要不同的策略。

然而,仔细思考一下我们会发现,不同业务场景的退款校验逻辑实际上是由一系列细分校验逻辑组合而成的,退款校验逻辑在不同的业务场景中是可以被重复使用的。

为什么不能将这些细分退款校验逻辑抽象为策略呢?例如,将过期不允许退款、已生效不可退款、超过最大退款次数不允许退款等校验逻辑抽象成为校验策略类。

各个业务场景组合多个校验策略,这样新增业务场景时,只需要组合多个校验策略即可。

如何组合校验策略

首先需要抽象校验策略接口: VerifyStrategy

85a0d09d955e08269527e0ba243e7c6d.jpeg

然后定义 VerifyScene 类

0af7b0e64eceb60c33845426630cff8f.jpeg

如何把对应具体策略类配置到VerifyScene中呢?本着 ”能不开发代码,就不要开发代码,优先使用配置!“的原则,我们选择使用Spring XML 文件配置。(在业务中台优先使用配置而非硬编码,否则这个问题不好回答。“业务方和中台都需要开发,为啥走你中台?”)

使用Spring XML 组合校验策略

在Spring XML文件中,可以声明VerifyScene类的Bean,初始化属性时,可以引用相关的校验策略。

026ee4f066e43c22ae27976cc5677292.jpeg


当需要新增业务场景时,首先需要评估现有的校验策略是否满足需求,不满足则新增策略。最终在XML文档中增加 VerifyScene 校验场景,引用相关的策略类。

这样新增业务场景时,只要校验逻辑是复用的,就无需新增扩展类,也无需开发代码,只需要在XML中配置策略组合即可。

在XML文档中可以添加注释,说明当前业务场景每一个校验单元的业务逻辑。在某种程度上,这个XML文档就是所有业务的退款校验的业务文档。甚至无需再写文档说明每个业务场景的退款策略如何如何~

和领导汇报以后,领导很是满意。对业务方开始宣称,我们的中台系统支持零开发,配置化接入退款能力。

结束了吗?没有 ,我们后来想到更加优雅的方式。

使用Spring Configuration 和 Lamada

Spring 提供了@Bean注解注入Bean,我们可以使用Spring @Bean方式声明校验策略类

f1acecd4cab3606cdd515ffbc50289eb.jpeg

通过以上方式,可以把checkPeriodVerifyStrategy 校验策略注入到Spring中,spring beanName就是方法名checkPeriodVerifyStrategy。

在Spring XML中可以使用 <ref bean="checkPeriodVerifyStrategy"/> 引用这个bean。

并且当点击XML中beanName时,可以直接跳转到 被@Bean修饰的checkPeriodVerifyStrategy方法。这样在梳理校验流程时,可以很方便地查看代码

点击这个BeanName,会跳转到对应的方法。(付费版Idea支持,社区版 Idea 不支持这个特性) 1e975286546b40fff4118267aea849bf.jpeg

总结

总结几个问题

  1. 策略模式目的是:根据不同的业务场景选择不同的策略来执行相应的逻辑

  2. 策略模式一定要进行细化,通过组合多个细分策略模式为一个更大的策略,避免使用继承方案。

  3. 使用Spring XML 组合多个策略模式,可以避免开发。减少新增策略类

  4. 使用Spring Configuration @Bean 将策略类注入Spring 更加优雅


作者:五阳神功
链接:https://juejin.cn/post/7295010992122101801
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1176820.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

如何在公网环境下使用移动端通过群晖管家管理部署自己家里局域网内的黑群晖

白嫖怪狂喜&#xff01;黑群晖也能使用群晖管家啦&#xff01; 文章目录 白嫖怪狂喜&#xff01;黑群晖也能使用群晖管家啦&#xff01;1.使用环境要求&#xff1a;2.下载安装群晖管家app3.随机地址登陆群晖管家app4.固定地址登陆群晖管家app 自己组装nas的白嫖怪们虽然也可以通…

第四章:Coverage-based testing

文章目录 Control-flow testingData-flow testingMutation analysisControl-flow testingCFG 注意事项Definitions for control-flow analysisexecution pathbranch / decisionconditionfeasible pathcoverage-based 标准Statement coverage (or node coverage)Branch coverage…

数据库的备份和恢复

备份 完全备份&#xff1a;整个数据库完整的进行备份 增量备份&#xff1a;在完全备份的基础上&#xff0c;对后续新增的变量进行备份 备份的需求&#xff1a; 1、在生产环境中&#xff0c;数据的安全至关重要。任何数据的丢失都可能产生非常严重的后果 2、数据为什么会丢失…

电力设备行业密钥管理系统的功能及特点 安当加密

电力设备行业密钥管理系统的主要功能包括&#xff1a; 密钥生成&#xff1a;密钥管理系统能够采用多因素身份验证技术&#xff0c;如指纹识别和动态口令等&#xff0c;确保生成的密钥对用户来说易于使用&#xff0c;同时又足够安全。密钥存储&#xff1a;应采用多层安全机制&a…

管道的介绍

管道 它是一个连接读写进程的文件&#xff0c;用户进程间数据交互和进程同步造作。管道是单向的&#xff0c;发送进程视管道为输出文件&#xff0c;将大量数据以字节流的形式送入管道&#xff1b;接收进程视管道为输入文件&#xff0c;接收管道的数据。 管道优缺点 1、管道…

【C++初阶】一、入门知识讲解(C++关键字、命名空间、C++输入输出、缺省参数、函数重载)

相关代码gitee自取&#xff1a; C语言学习日记: 加油努力 (gitee.com) 接上期&#xff1a; 【数据结构初阶】十一、归并排序(比较排序)的讲解和实现 &#xff08;递归版本 非递归版本 -- C语言实现&#xff09;-CSDN博客 引入&#xff1a;什么是C C语言是结构化和模块化的…

HomeAssistant添加HACS插件并实现公网控制米家,HomeKit等智能家居

HomeAssistant添加HACS插件并实现公网控制米家&#xff0c;HomeKit等智能家居 文章目录 HomeAssistant添加HACS插件并实现公网控制米家&#xff0c;HomeKit等智能家居基本条件一、下载HACS源码二、添加HACS集成三、绑定米家设备 ​ 上文介绍了如何实现群晖Docker部署HomeAssist…

pytorch实现 --- 手写数字识别

本篇文章是博主在人工智能等领域学习时&#xff0c;用于个人学习、研究或者欣赏使用&#xff0c;并基于博主对人工智能等领域的一些理解而记录的学习摘录和笔记&#xff0c;若有不当和侵权之处&#xff0c;指出后将会立即改正&#xff0c;还望谅解。文章分类在Pytorch&#xff…

天津热力管网监测系统丨高效、稳定的供热解决方案

热力管网监测系统是一种用于监测和控制系统热力管道的智能技术。热力管网监测系统通过将传感仪器建设在热力管道上&#xff0c;实现对管道内温度、压力、流量等参数的实时监测&#xff0c;同时将数据传输到控制中心进行数据分析&#xff0c;以保障热力管道的安全稳定运行。 中央…

不学51直接学stm32可以吗?学stm32需要哪些基础?

不学51直接学stm32可以吗&#xff1f;学stm32需要哪些基础&#xff1f; 不管那些大佬技术多么牛逼&#xff0c;大多数入门都是从51单片机开始。 最近有一些入门的小伙伴问我说看到同学都从直接从STM32开始干了。最近很多小伙伴找我&#xff0c;说想要一些stm32的资料&#xff…

C++ reference

cppreference.com 《现代C语言核心特性解析》 这是一本 C 进阶图书&#xff0c;全书分为 42 章&#xff0c;深入探讨了从 C11 到 C20 引入的核心特性。 本书不仅通过大量的实例代码讲解特性的概念和语法&#xff0c;还从编译器的角度分析特性的实现原理&#xff0c;让读者…

王道p18 第11题 现在有两个等长升序序列 A和 B,试设计一个在时间和空间两方面都尽可能高效的算法,找出两个序列 A和B的中位数。

视频讲解&#x1f447;&#xff1a; p18 第10题 c语言代码实现王道数据结构课后代码题_哔哩哔哩_bilibili 本题代码如下 int search(int a[], int b[], int c[]) {int i 0;int j 0;int k 0;while (i < 5 && j < 5){if (a[i] < b[j])c[k] a[i];elsec[k…

NOIP2005提高组第二轮T3:传纸条

题目链接 NOIP2005提高组第二轮T3&#xff1a;传纸条 题目描述 小渊和小轩是好朋友也是同班同学&#xff0c;他们在一起总有谈不完的话题。一次素质拓展活动中&#xff0c;班上同学安排坐成一个 m m m 行 n n n 列的矩阵&#xff0c;而小渊和小轩被安排在矩阵对角线的两端…

GraphCodeBert:基于数据流的代码表征预训练模型

GraphCodeBert https://arxiv.org/abs/2009.08366 1 模型结构 使用多层双向 Transformer 变量定义 &#xff1a; C&#xff1a;源码集合W&#xff1a;文本集合V&#xff1a;变量集合E&#xff1a;变量间的边的集合 输入&#xff1a;把注释&#xff0c;源代码和变量集连接为…

【MySQL基本功系列】第一篇 先熟悉MySQL的运行逻辑

​ 我将推出一系列关于MySQL的博客文章&#xff0c;涵盖了从入门到深入底层的原理。这些文章将包括MySQL的运行逻辑、InnoDB存储引擎、SQL优化、undo log、bin log等多个方面的知识。希望这些文章能为你提供宝贵的信息和洞见&#xff0c;并帮助你更好地理解和应用MySQL。同时&a…

国产系列 | Atlas 300I Pro 推理卡性能、应用场景、技术规格介绍

Atlas 300I Pro 推理卡是基于昇腾AI处理器的新一代高性能推理卡&#xff0c;融合“通用处理器、AI Core、编解码”于一体&#xff0c;提供超强AI推理、目标检索等功能&#xff0c;具有超强算力、超高能效、高性能特征检索、安全启动等优势&#xff0c;可广泛应用于OCR识别、语音…

UMS攸信技术与欣奕华复合机器人携手共进,领跑智能制造未来!

近年来&#xff0c;全球机器人领域的相关创新机构与科技企业不断探索人工智能、人机协作、多技术融合等领域&#xff0c;推动机器人在仓储运输、智能工厂、医疗康复等领域的深入应用。 2023年10月19日&#xff0c;攸信技术与浙江欣奕华达成战略合作&#xff0c;成为其产品特约经…

Mysql Cluster (NDB - Network Database) - 分布式

Mysql高可用架构 复制&#xff08;Replication&#xff09; 是本文中所有 MySQL 技术的基础。包括&#xff1a;异步复制、半同步复制&#xff0c;增强半同步复制。InnoDB 副本集&#xff08;MySQL InnoDB ReplicaSet&#xff09; 无缝衔接其他 MySQL 官方提供的应用程序&#…

Java智慧工地管理平台可视化大数据建造工地APP源码

建筑行业是国民经济的重要物质生产部门和支柱产业之一&#xff0c;同时&#xff0c;建筑业也是一个安全事故多发的高危行业。如何加强施工现场安全管理、降低事故发生频率、杜绝各种违规操作和不文明施工、提高建筑工程质量&#xff0c;是摆在各级政府部门、施工企业面前的一道…

多机位直播案例

目录 1、案例简述 2、设备准备&#xff1a; &#xff08;1&#xff09;笔记本电脑 &#xff08;2&#xff09;手机 &#xff08;3&#xff09;触控一体机 &#xff08;4&#xff09;教室前端监控摄像机 &#xff08;5&#xff09;教室后端监控摄像机 &#xff08;6&…