【策略模式在项目中的实际应用】
业务场景
最最近项目中有这样的一个业务场景:
用户下单->管理员审核->配送员接单->配送中->送达–>签收->完成
整个业务以这种流程的形式存在,每个流程状态的业务不一样,考虑到多种状态如果直接写一个接口肯定会嵌套太多的if else,于是这里使用了策略模式。
对策略模式的基础这里不做概述
接口设计
策略行为接口的设计
public interface OrderTraceChangeStrategy {/*** 用于判断策略是否支持** @param traceDto* @param wxPreOrder* @return*/boolean support(WxPreOrderTraceDto traceDto, WxPreOrder wxPreOrder);/*** 业务参数校验** @param traceDto* @param wxPreOrder* @return*/void check(WxPreOrderTraceDto traceDto, WxPreOrder wxPreOrder);/*** 状态变操作** @param traceDto* @param wxPreOrder*/void change(WxPreOrderTraceDto traceDto, WxPreOrder wxPreOrder);
}
定义了一个接口,该接口提供了三个方法:support、check、change。
support方法用于判断策略是否支持
check方法用于对业务参数进行校验
change方法用于执行状态转换以及其他业务操作操作
策略实现类的设计
这里列举一个实现类
@Slf4j
@Component
public class AuditRefuseStrategyImpl implements OrderTraceChangeStrategy {@Resourceprivate WxPreOrderService wxPreOrderService;@Overridepublic boolean support(WxPreOrderTraceDto traceDto, WxPreOrder wxPreOrder) {return traceDto.getAfterPreOrderStatusEnum()==PreOrderStatusEnum.REJECT_REQ;}@Overridepublic void check(WxPreOrderTraceDto traceDto, WxPreOrder wxPreOrder) {//当前订单为待审核才可以拒单Assert.isTrue(wxPreOrder.getOrderStatus().equals(PreOrderStatusEnum.WAIT_CHECK.getCode()), WeiXinError.COMMON_ERROR, "当前订单状态非待审核状态,不支持拒单");}@Override@Transactional(rollbackFor = Throwable.class)public void change(WxPreOrderTraceDto traceDto, WxPreOrder wxPreOrder) {//更新主表数据WxPreOrder wxPreOrderUpdate = new WxPreOrder();wxPreOrderUpdate.setId(wxPreOrder.getId());//变更为拒单状态wxPreOrderUpdate.setOrderStatus(PreOrderStatusEnum.REJECT_REQ.getCode());wxPreOrderUpdate.setRejectReqReason(traceDto.getRemark());wxPreOrderService.updateById(wxPreOrderUpdate);log.info("订单状态流转,订单id:{},审核拒绝:{}------------>{}", wxPreOrder.getId(), wxPreOrder.getOrderStatus(), traceDto.getAfterPreOrderStatusEnum().getCode());}
}
业务层的应用
@Autowired
private List<OrderTraceChangeStrategy> orderTraceChangeStrategy;@Override@Transactional(rollbackFor = Throwable.class)public void traceOrderStatus(WxPreOrderTraceDto traceDto) {//查询当前订单信息WxPreOrder preOrder = wxPreOrderService.getById(traceDto.getOrderId());Assert.isNotNull(preOrder, WeiXinError.COMMON_ERROR, "预订单不存在");for (OrderTraceChangeStrategy item : orderTraceChangeStrategy) {//获取支持的策略boolean support = item.support(traceDto, preOrder);if (support) {//参数校验item.check(traceDto, preOrder);//业务处理item.change(traceDto, preOrder);//公共业务保存订单状态变更流水信息WxPreOrderSaveFlowDto saveFlowDto = WxPreOrderSaveFlowDto.builder().preStatus(preOrder.getOrderStatus()).afterStatus(traceDto.getAfterPreOrderStatusEnum().getCode()).orderId(preOrder.getId()).build();saveOrderFlow(saveFlowDto);//处理完业务直接返回return;}}//上面已经return了 如果走到这里说明前端传递的参数没有和任何策略命中,直接抛出异常Assert.Error( WeiXinError.COMMON_ERROR, "错误的订单状态");}
重点来了:这里使用一次注入多个策略的方式,直接注入到容器一个集合,对于这些集合中的策略执行哪一个,使用
循环判断的方式。
接受参数使用枚举的方式,使用枚举对应类型强校验,不传参会相应前端页面400。
关于枚举在项目中的使用骚操作,后面的文章还会更新。请持续关注,保证你眼前一亮。
策略业务对应的入参:
Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class WxPreOrderTraceDto {@ApiModelProperty("订单ID")@NotNull(message = "订单ID不能为空")private Long orderId;/*** 使用枚举强校验,前端传错会报400*/@ApiModelProperty("订单变更后的状态")@NotNull(message = "流程变更状态不能为空")private PreOrderStatusEnum afterPreOrderStatusEnum;@ApiModelProperty("原因,备注")private String remark;
这样就实现了不同流程状态的业务拆分,即使再多的状态也不用担心代码无法维护了。
其实还有一个需要解释一下,在业务层,下面这些代码,其实属于设计模式中的模板方法,将这些业务统一抽取成一个
模版,执行类似的业务,也可以在抽象类中去继续封装这些算法行为。这里暂时不做赘述。
//参数校验item.check(traceDto, preOrder);//业务处理item.change(traceDto, preOrder);//公共业务保存订单状态变更流水信息WxPreOrderSaveFlowDto saveFlowDto = WxPreOrderSaveFlowDto.builder().preStatus(preOrder.getOrderStatus()).afterStatus(traceDto.getAfterPreOrderStatusEnum().getCode()).orderId(preOrder.getId()).build();saveOrderFlow(saveFlowDto);//处理完业务直接返回
总结一下
- 定义策略接口,定义不同行为
- 通过List批量注入不同策略
- 通过不同状态枚举判断不同状态的业务,获取不同状态的策略类
- 通过模板方法,抽取公共业务
相关文章:
【策略模式在项目中的实际应用】
业务场景 最最近项目中有这样的一个业务场景: 用户下单->管理员审核->配送员接单->配送中->送达–>签收->完成 整个业务以这种流程的形式存在,每个流程状态的业务不一样,考虑到多种状态如果直接写一个接口肯定会嵌套太多…...
昇思25天学习打卡营第14天|计算机视觉
昇思25天学习打卡营第14天 文章目录 昇思25天学习打卡营第14天FCN图像语义分割语义分割模型简介网络特点数据处理数据预处理数据加载训练集可视化 网络构建网络流程 训练准备导入VGG-16部分预训练权重损失函数自定义评价指标 Metrics 模型训练模型评估模型推理总结引用 打卡记录…...
将json数组格式转成数组
start cmd [ 27 01 f7 01 24 38 02 b7 42 6e ee 2f 69 46 72 21 74 44 c4 22 7a 92 d8 6a de 66 61 b1 1e 2f de ee 5c 31 57 db df 01 31 2d c9 01 01 c0 FB ] set_ulpk {“jsonrpc”:“2.0”,“type”:2,“id”:0,“method”:“method”,“message”:{“VALUE”:[56,2,183,66…...
接口测试之测试原则、测试用例、测试流程详解
🍅 点击文末小卡片 ,免费获取软件测试全套资料,资料在手,涨薪更快 一、接口的介绍 软件测试中,常说的接口有两种:图形用户接口(GUI,人与程序的接口)、应用程序编程接口&…...
证书上的服务器名错误解决方法
方法 win r ,输入mmc 点击文件——>添加/删除管理单元 找到证书——> 添加 根据自己的存放选择存放位置 点击控制台根节点——> 受信任的根证书颁发机构——>导入 若还出现问题,则参考https://blog.csdn.net/mm120138687/article/details/…...
前端:上传2进制图片
1、let formData new FormData(); 2、添加要传的字段:formData.append("avatarfile", data); (key,value) 3、上传文件 function uploadImg() {// 1定义FormDatalet formData new FormData();// 2添加字段formData.append("…...
web前端 React 框架面试200题(三)
面试题 65. 在使用 React Router时,如何获取当前页面的路由或浏览器中地址栏中的地址? 参考回答: 在当前组件的 props中,包含 location属性对象,包含当前页面路由地址信息,在 match中存储当前路由的参数等…...
交流负载箱:电力系统的节能利器
交流负载箱是模拟电网中实际负载的装置,它能够精确地模拟各种电器设备的耗电情况,为电力系统的节能提供了重要的工具。在电力系统中,交流负载箱的应用非常广泛,它可以用于电力系统的设计、运行和维护,以及电力设备的测…...
【思科】链路聚合实验配置和背景
【思科】链路聚合实验配置和背景 背景链路聚合基本概念链路聚合聚合接口 思科链路聚合协议01.PAgP协议02.LACP协议 思科链路聚合模式LACP协议模式PAgP协议模式ON模式 实验准备配置二层链路聚合LACP协议模式SW1SW2PC1PC2查看LACP聚合组建立情况查看LACP聚合端口情况查看逻辑聚合…...
使用 vue-element-plus-admin 框架遇到的问题记录
项目打包遇到的问题: 打包语句:pnpm run build:pro 报错信息: Error: [vite]: Rollup failed to resolve import "E:/workplace_gitee/xxx/node_modules/.pnpm/element-plus2.5.5_vue3.4.15/node_modules/element-plus/es/components…...
从零开始手写STL库:List
从零开始手写STL库–List部分 Github链接:miniSTL 文章目录 从零开始手写STL库–List部分List是什么?List需要包含什么函数1)基础成员函数2)核心功能3)其他功能 基础成员函数的编写核心功能的编写其他功能编写总结 List是什么&am…...
蒙特卡洛采样
目录 蒙特卡洛采样的计算逻辑计算步骤:1. 定义问题2. 确定采样范围3. 生成随机样本点4. 计算函数值5. 估计期望值或积分值6. 计算误差具体示例:1. 定义问题2. 确定采样范围3. 生成随机样本点4. 计算函数值5. 估计积分值6. 计算误差总结蒙特卡洛采样是一种通过随机生成样本点来…...
Apache虚拟主机VirtualHost配置项详解
在Apache中,VirtualHost容器用于定义一个虚拟主机的配置,它允许在单一的物理服务器上托管多个不同的网站,每个网站可以有自己的域名、文档根目录、错误日志等。VirtualHost内的配置项非常灵活,可以包含从基本的网站信息到高级的URL重写和安全设置。 以下是一些常见的Virtu…...
OpenAI从GPT-4V到GPT-4O,再到GPT-4OMini简介
OpenAI从GPT-4V到GPT-4O,再到GPT-4OMini简介 一、引言 在人工智能领域,OpenAI的GPT系列模型一直是自然语言处理的标杆。随着技术的不断进步,OpenAI推出了多个版本的GPT模型,包括视觉增强的GPT-4V(GPT-4 with Vision&…...
从人工巡检到智能防控:智慧油气田安全生产的新视角
一、背景需求 随着科技的飞速发展,视频监控技术已成为各行各业保障安全生产、提升管理效率的重要手段。特别是在油气田这一特殊领域,由于其工作环境复杂、安全风险高,传统的监控方式已难以满足实际需求。因此,基于视频监控AI智能…...
【黑马java基础】Lamda, 方法引用,集合{Collection(List, Set), Map},Stream流
文章目录 JDK8新特性:Lambda表达式认识Lambda表达式Lambda表达式的省略规则 JDK8新特性:方法引用静态方法的引用实例方法的引用特定类型方法的引用构造器的应用 集合➡️Collection单列集合体系Collection的常用方法Collection的遍历方法迭代器增强for循…...
Stable Diffusion 使用详解(1)---- 提示词及相关参数
目录 背景 提示词 内容提示词 人物及主体特征 场景 环境光照 画幅视角 注意事项及示例 标准化提示词 画质等级 风格与真实性 具体要求 背景处理 光线与色彩 负向提示词 小结 常用工具 另外几个相关参数 迭代步数 宽度与高度 提示词引导系数 图片数量 背景…...
数据结构和算法(刷题) - 无序数组排序后的最大相邻差
无序数组排序后的最大相邻差 问题:一个无序的整型数组,求出该数组排序后的任意两个相邻元素的最大差值?要求时间和空间复杂度尽可能低。 三种方法: 排序后计算比较 简介:用任意一种时间复杂度为 O ( n log n ) O…...
HOW - React 处理不紧急的更新和渲染
目录 useDeferredValueuseTransitionuseIdleCallback 在 React 中,有一些钩子函数可以帮助你处理不紧急的更新或渲染,从而优化性能和用户体验。 以下是一些常用的相关钩子及其应用场景: useDeferredValue 用途:用于处理高优先级…...
基于A律压缩的PCM脉冲编码调制通信系统simulink建模与仿真
目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 4.1A律压缩的原理 4.2 PCM编码过程 4.3 量化噪声与信噪比 5.算法完整程序工程 1.算法运行效果图预览 (完整程序运行后无水印) 2.算法运行软件版本 matlab2022a 3.部分核心程序 &#…...
业务系统对接大模型的基础方案:架构设计与关键步骤
业务系统对接大模型:架构设计与关键步骤 在当今数字化转型的浪潮中,大语言模型(LLM)已成为企业提升业务效率和创新能力的关键技术之一。将大模型集成到业务系统中,不仅可以优化用户体验,还能为业务决策提供…...
Mybatis逆向工程,动态创建实体类、条件扩展类、Mapper接口、Mapper.xml映射文件
今天呢,博主的学习进度也是步入了Java Mybatis 框架,目前正在逐步杨帆旗航。 那么接下来就给大家出一期有关 Mybatis 逆向工程的教学,希望能对大家有所帮助,也特别欢迎大家指点不足之处,小生很乐意接受正确的建议&…...
蓝牙 BLE 扫描面试题大全(2):进阶面试题与实战演练
前文覆盖了 BLE 扫描的基础概念与经典问题蓝牙 BLE 扫描面试题大全(1):从基础到实战的深度解析-CSDN博客,但实际面试中,企业更关注候选人对复杂场景的应对能力(如多设备并发扫描、低功耗与高发现率的平衡)和前沿技术的…...
Java多线程实现之Callable接口深度解析
Java多线程实现之Callable接口深度解析 一、Callable接口概述1.1 接口定义1.2 与Runnable接口的对比1.3 Future接口与FutureTask类 二、Callable接口的基本使用方法2.1 传统方式实现Callable接口2.2 使用Lambda表达式简化Callable实现2.3 使用FutureTask类执行Callable任务 三、…...
使用van-uploader 的UI组件,结合vue2如何实现图片上传组件的封装
以下是基于 vant-ui(适配 Vue2 版本 )实现截图中照片上传预览、删除功能,并封装成可复用组件的完整代码,包含样式和逻辑实现,可直接在 Vue2 项目中使用: 1. 封装的图片上传组件 ImageUploader.vue <te…...
spring:实例工厂方法获取bean
spring处理使用静态工厂方法获取bean实例,也可以通过实例工厂方法获取bean实例。 实例工厂方法步骤如下: 定义实例工厂类(Java代码),定义实例工厂(xml),定义调用实例工厂ÿ…...
现代密码学 | 椭圆曲线密码学—附py代码
Elliptic Curve Cryptography 椭圆曲线密码学(ECC)是一种基于有限域上椭圆曲线数学特性的公钥加密技术。其核心原理涉及椭圆曲线的代数性质、离散对数问题以及有限域上的运算。 椭圆曲线密码学是多种数字签名算法的基础,例如椭圆曲线数字签…...
短视频矩阵系统文案创作功能开发实践,定制化开发
在短视频行业迅猛发展的当下,企业和个人创作者为了扩大影响力、提升传播效果,纷纷采用短视频矩阵运营策略,同时管理多个平台、多个账号的内容发布。然而,频繁的文案创作需求让运营者疲于应对,如何高效产出高质量文案成…...
面向无人机海岸带生态系统监测的语义分割基准数据集
描述:海岸带生态系统的监测是维护生态平衡和可持续发展的重要任务。语义分割技术在遥感影像中的应用为海岸带生态系统的精准监测提供了有效手段。然而,目前该领域仍面临一个挑战,即缺乏公开的专门面向海岸带生态系统的语义分割基准数据集。受…...
C#中的CLR属性、依赖属性与附加属性
CLR属性的主要特征 封装性: 隐藏字段的实现细节 提供对字段的受控访问 访问控制: 可单独设置get/set访问器的可见性 可创建只读或只写属性 计算属性: 可以在getter中执行计算逻辑 不需要直接对应一个字段 验证逻辑: 可以…...
