用责任链模式改造 if else

我的上一篇文章,因为if else 多了,捣鼓很久,今天用责任链模式改造一下。

代码写着写着,if else if 逻辑忘记了,哎。。。-CSDN博客
责任链模式(Chain of Responsibility Pattern)
1. 什么是责任链模式?
责任链模式是一种行为设计模式,它允许请求沿着处理者链传递,直到其中一个处理者处理它。每个处理者都可以决定是否处理请求或者将其传递给链中的下一个处理者。
2. 责任链模式的优点
降低耦合度:请求发送者不需要知道请求的最终处理者是谁,只需要知道请求会被某个处理者处理。
灵活配置处理链:可以根据需要动态地增加或删除处理者,而不影响其他处理者。
增强系统扩展性:新的处理者可以很容易地添加到链中,从而扩展系统的功能。
3. 责任链模式的应用场景
权限控制:多个权限检查器组成一个链,逐级检查用户的权限。
日志处理:多个日志处理器组成一个链,逐级处理日志消息。
支付处理:多种支付方式组成一个链,逐级处理支付请求。
4. 责任链模式的实现
现在如下代码改成 责任链模式

        //代理价>销售价if (agentPrice.compareTo(goodsPrice) > 0) {isNeedLock=true;reason="代理价>销售价";reasonType="1";log.info("agentPrice.compareTo(goodsPrice) > 0 ");}else if (agentPrice.compareTo(BigDecimal.ZERO) > 0) {//(销售价-代理价)/代理价<5%double num = (goodsPrice.subtract(agentPrice)).divide(agentPrice,6, RoundingMode.HALF_UP).multiply(new BigDecimal(100)).doubleValue();if (num < 5) {isNeedLock=true;reason="(销售价-代理价)/代理价<5%";reasonType="2";log.info("agentPrice.compareTo(BigDecimal.ZERO) > 0");}}else if (supplyPrice.compareTo(agentPrice) > 0) {isNeedLock = true;reason = "供货价大于代理价";reasonType = "5";log.info(" supplyPrice.compareTo(agentPrice) > 0 ");}

首先分析需要代码,这里的每一个 if else 都有机会执行,一个执行了,其他的 if else 就不会执行了。

入参需要三个价格,那么可以将这个价格放到一个类里面, 这里执行结果有四种,那么可以创建一个枚举类存放,可以在初始化入参的时候设置为默认枚举。

入参请求和结果类 PriceCheckRequest 

/*** @author hds*/
@Data
public class PriceCheckRequest {private BigDecimal goodsPrice;private BigDecimal agentPrice;private BigDecimal supplyPrice;private PriceCheckEnum priceCheckEnum;public PriceCheckRequest(BigDecimal goodsPrice, BigDecimal agentPrice, BigDecimal supplyPrice) {this.goodsPrice = goodsPrice;this.agentPrice = agentPrice;this.supplyPrice = supplyPrice;}public PriceCheckRequest(Product product) {this.goodsPrice = Optional.ofNullable(product.getProductPrice()).orElse(BigDecimal.ZERO);this.agentPrice = Optional.ofNullable(product.getAgentPrice()).orElse(BigDecimal.ZERO);this.supplyPrice = Optional.ofNullable(product.getSupplyPrice()).orElse(BigDecimal.ZERO);priceCheckEnum = PriceCheckEnum.DEFAULT;}
}

结果枚举类

@Getter
public enum PriceCheckEnum {/*    request.setNeedLock(true);request.setReason("代理价>销售价");request.setReasonType("1");request.setNeedLock(true);request.setReason("(销售价-代理价)/代理价<5%");request.setReasonType("2");request.setNeedLock(true);request.setReason("供货价大于代理价");request.setReasonType("5");*/DEFAULT("0", "", false),AGENT_PRICE_GREATER_THAN_SALE_PRICE("1", "代理价>销售价", true),SALE_PRICE_DIFFERENCE_PERCENTAGE("2", "(销售价-代理价)/代理价<5%", true),SUPPLIER_PRICE_GREATER_THAN_AGENT_PRICE("5", "供货价>代理价", true);private final String reasonType;private final String reason;private final Boolean needLock;PriceCheckEnum(String reasonType, String reason, boolean needLock) {this.reasonType = reasonType;this.reason = reason;this.needLock = needLock;}

解下类就要创建一个 价格检查的抽象类 

PriceCheckHandler 其中 next 属性是执行 下一个处理器
@Setter
public abstract class PriceCheckHandler {protected PriceCheckHandler next;public abstract void handle(PriceCheckRequest request);public  void check(PriceCheckRequest request){if (!request.getPriceCheckEnum().getNeedLock()){if (next != null) {next.handle(request);}}}
}

代理价大于销售价 处理器

AgentPriceGreaterThanGoodsPriceHandler
public class AgentPriceGreaterThanGoodsPriceHandler extends PriceCheckHandler {@Overridepublic void handle(PriceCheckRequest request) {if (BigDecimalUtil.isGreaterThan(request.getAgentPrice(),request.getGoodsPrice())) {request.setPriceCheckEnum(PriceCheckEnum.AGENT_PRICE_GREATER_THAN_SALE_PRICE);}check(request);}
}

供货价大于代理价处理器

SupplyPriceGreaterThanAgentPriceHandler
public class SupplyPriceGreaterThanAgentPriceHandler extends PriceCheckHandler {@Overridepublic void handle(PriceCheckRequest request) {if (BigDecimalUtil.isGreaterThan( request.getSupplyPrice(), request.getAgentPrice())) {request.setPriceCheckEnum(PriceCheckEnum.SUPPLIER_PRICE_GREATER_THAN_AGENT_PRICE);}check(request);}
}
(销售价-代理价)/代理价<5% 处理器
AgentPricePercentageDifferenceHandler
public class AgentPricePercentageDifferenceHandler extends PriceCheckHandler {@Overridepublic void handle(PriceCheckRequest request) {if ( BigDecimalUtil.isGreaterThan(request.getAgentPrice(),BigDecimal.ZERO) ) {double num = (request.getGoodsPrice().subtract(request.getAgentPrice())).divide(request.getAgentPrice(), 6, RoundingMode.HALF_UP).multiply(new BigDecimal(100)).doubleValue();if (num < 5) {request.setPriceCheckEnum(PriceCheckEnum.SALE_PRICE_DIFFERENCE_PERCENTAGE);}check(request);}check(request);}
}

默认处理器

DefaultPriceHandler 默认返回价格检查通过,需要把它放在责任链的最后处理器
public class DefaultPriceHandler extends PriceCheckHandler {@Overridepublic void handle(PriceCheckRequest request) {request.setPriceCheckEnum(PriceCheckEnum.DEFAULT);}
}

责任链创建类 (简单的建造者模式)

ChainBuilder
public class ChainBuilder {private PriceCheckHandler head;public static ChainBuilder chainBuilder = new ChainBuilder();static {chainBuilder.addFirst(new DefaultPriceHandler());chainBuilder.addFirst(new AgentPricePercentageDifferenceHandler());chainBuilder.addFirst(new SupplyPriceGreaterThanAgentPriceHandler());chainBuilder.addFirst(new AgentPriceGreaterThanGoodsPriceHandler());}public void addFirst(PriceCheckHandler handler) {handler.setNext(head);head = handler;}public void process(PriceCheckRequest request) {if (head != null) {head.handle(request);}}
}

最后测试


@Slf4j
public class ChainBuilderTest {@Testpublic void testChain(){Product product = new Product();product.setAgentPrice(new BigDecimal("59.00"));product.setProductPrice(new BigDecimal("60.00"));product.setSupplyPrice(new BigDecimal("50.00"));PriceCheckRequest priceCheckRequest = new PriceCheckRequest(product);ChainBuilder.chainBuilder.process(priceCheckRequest);log.info("商品价格校验结果:{}", JSONUtil.toJsonStr(priceCheckRequest) );product.setAgentPrice(new BigDecimal("70.00"));product.setProductPrice(new BigDecimal("60.00"));product.setSupplyPrice(new BigDecimal("50.00"));//AGENT_PRICE_GREATER_THAN_SALE_PRICEpriceCheckRequest = new PriceCheckRequest(product);ChainBuilder.chainBuilder.process(priceCheckRequest);log.info("商品价格校验结果:{}", JSONUtil.toJsonStr(priceCheckRequest) );product.setAgentPrice(new BigDecimal("60.00"));product.setProductPrice(new BigDecimal("60.00"));product.setSupplyPrice(new BigDecimal("80.00"));//SUPPLIER_PRICE_GREATER_THAN_AGENT_PRICEpriceCheckRequest = new PriceCheckRequest(product);ChainBuilder.chainBuilder.process(priceCheckRequest);log.info("商品价格校验结果:{}", JSONUtil.toJsonStr(priceCheckRequest) );product.setAgentPrice(new BigDecimal("60.00"));product.setProductPrice(new BigDecimal("80.00"));product.setSupplyPrice(new BigDecimal("60.00"));//DEFAULTpriceCheckRequest = new PriceCheckRequest(product);ChainBuilder.chainBuilder.process(priceCheckRequest);log.info("商品价格校验结果:{}", JSONUtil.toJsonStr(priceCheckRequest) );}}

输出结果,

好了今天就到这里,有兴趣的同学可以自己试一下。

另外将 AgentPricePercentageDifferenceHandler 放到倒数第二个,是可以延迟计算。

还可以再在处理类处理了请求的时候,将处理次数加一进行统计,经过一段时间,用定时任务统计每个处理器的次数,将次数多的处理器动态调整放到前面。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux下的基本指令/命令(一)

目录 基本命令 1. Is命令/指令: 罗列当前目录下指定的文件或者目录. 2. pwd命令&#xff1a; 查看当前工作的路径 3. cd命令&#xff1a; 切换到指定路径下。 只能切换到目录中 4. tree命令: 树状显式目录 使用前要输入命令 yum install -y tree &#xff0c;用来安装一个…

Redis入门第二步:Redis数据类型详解

摘要&#xff1a; 欢迎继续跟随《Redis新手指南&#xff1a;从入门到精通》专栏的步伐&#xff01;在本文中&#xff0c;我们将深入探讨Redis支持的各种数据类型&#xff0c;这些类型是Redis强大功能的核心。通过学习不同的数据类型&#xff0c;你将能够根据具体的应用需求选择…

【Spring基础3】- Spring的入门程序

目录 3-1 Spring的下载3-2 Spring的 jar 包3-3 第一个 Spring程序第一步&#xff1a;添加spring context的依赖&#xff0c;pom.xml配置如下第二步&#xff1a;添加junit依赖第三步&#xff1a;定义bean&#xff1a;User第四步&#xff1a;编写spring的配置文件&#xff1a;bea…

技术成神之路:设计模式(十八)适配器模式

介绍 适配器模式&#xff08;Adapter Pattern&#xff09;是一种结构型设计模式&#xff0c;它允许接口不兼容的类可以协同工作&#xff0c;通过将一个类的接口转换成客户端所期望的另一个接口&#xff0c;使得原本由于接口不兼容而不能一起工作的类可以一起工作。 1.定义 适配…

python编程开发“人机猜拳”游戏

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;开发者-曼亿点 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 曼亿点 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a…

计算机毕业设计 基于深度学习的短视频内容理解与推荐系统的设计与实现 Python+Django+Vue 前后端分离 附源码 讲解 文档

&#x1f34a;作者&#xff1a;计算机编程-吉哥 &#x1f34a;简介&#xff1a;专业从事JavaWeb程序开发&#xff0c;微信小程序开发&#xff0c;定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事&#xff0c;生活就是快乐的。 &#x1f34a;心愿&#xff1a;点…

【架构】前台、中台、后台

文章目录 前台、中台、后台1. 前台&#xff08;Frontend&#xff09;特点&#xff1a;技术栈&#xff1a; 2. 中台&#xff08;Middleware&#xff09;特点&#xff1a;技术栈&#xff1a; 3. 后台&#xff08;Backend&#xff09;特点&#xff1a;技术栈&#xff1a; 示例场景…

万界星空科技铜拉丝行业MES系统,实现智能化转型

一、铜拉丝行业生产管理的难点主要体现在以下几个方面&#xff1a; 1、标准严格&#xff1a;铜线产品对质量的要求极高&#xff0c;特别是在电气性能、导电性、耐腐蚀性等方面&#xff0c;任何微小的瑕疵都可能影响产品的使用效果和安全性。 2、过程监控&#xff1a;生产过程…

极速 JavaScript 打包器:esbuild

文章目录 前言什么是esbuild&#xff1f;esbuild如何实现如此出色的性能&#xff1f;基本配置入口文件输出文件模块格式targetplatformexternalbanner和footer 结论 前言 esbuild是一个快速、可扩展的JavaScript打包器和压缩器&#xff0c;它的目标是成为最快的打包器。它使用…

【C++篇】启航——初识C++(下篇)

接上篇【C篇】启航——初识C&#xff08;上篇&#xff09; 目录 一、引用 1.引用的概念 2.引用的基本语法 3.引用的特点 3.1 别名 3.2 不占用额外内存 3.3 必须初始化 3.4 不能为 NULL 4.引用的使用 4.1 函数参数传递 4.2 返回值 4.3 常量引用 5.引用和指针的关…

Spring Task 2024/9/30

Spring Task是Spring框架提供的任务调度工具&#xff0c;可以按照约定时间自动执行某个代码逻辑。 作用&#xff1a;定时自动执行某段java代码。 cron表达式 在线Cron表达式生成器 (qqe2.com)&#x1f448;在线生成网站 入门案例 SkyApplication 启动类 package com.sky;im…

盛事启幕 | 第三届OpenHarmony技术大会重磅官宣,邀您共绘智联未来

未来已来&#xff0c;科技何向&#xff1f; ——10月12日-13日众多大咖齐聚上海 聚焦OpenHarmony生态前沿 与您一同解码技术的下一片蓝海

C# 委托(Delegate)一

一.Delegate的定义说明&#xff1a; C# 中的委托&#xff08;Delegate&#xff09;就是类似于 C 或 C 中函数的指针。Delegate 是存有对某个方法引用的一种引用类型变量&#xff0c;引用可在运行时是可以被改变的&#xff0c;特别适用于实现事件和回调方法。所有的Delegate都是…

网络基础概念和 socket 编程

网络基础概念和 socket 编程 学习目标&#xff1a; 了解 OSI 七层模型、TCP/IP 四层模型结构了解常见的网络协议格式掌握网络字节序和主机字节序之间的转换理解 TCP 服务器端通信流程理解 TCP 客户端通信流程实现 TCP 服务器端和客户端的代码 推荐一个非常好的学习资料仓库 协…

简单线性回归分析-基于R语言

本题中&#xff0c;在不含截距的简单线性回归中&#xff0c;用零假设对统计量进行假设检验。首先&#xff0c;我们使用下面方法生成预测变量x和响应变量y。 set.seed(1) x <- rnorm(100) y <- 2*xrnorm(100) &#xff08;a&#xff09;不含截距的线性回归模型构建。 &…

计算机网络(九) —— Tcp协议详解

目录 一&#xff0c;关于Tcp协议 二&#xff0c;Tcp报头字段解析 2.0 协议字段图示 2.1 两个老问题 2.2 16位窗口大小 2.3 32位序号和确认序号 2.4 6个标记位 三&#xff0c;Tcp保证可靠性策略 3.1 确认应答机制&#xff08;核心&#xff09; 3.2 超时重传机制 3.3 …

基于开源WQ装备知识图谱的智能问答优化2

基于笔者之前写的博客基础上&#xff1a;https://blog.csdn.net/zhanghan11366/article/details/142139488【基于开源WQ装备知识图谱的智能问答全流程构建】进行优化。新增处理基于特定格式下的WQ文档&#xff0c;抽取文档的WQ属性和关系&#xff0c;并抽取对应WQt图片存储至mi…

位运算(3)_判定字符是否唯一_面试题

个人主页&#xff1a;C忠实粉丝 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 C忠实粉丝 原创 位运算(3)_判定字符是否唯一_面试题 收录于专栏【经典算法练习】 本专栏旨在分享学习算法的一点学习笔记&#xff0c;欢迎大家在评论区交流讨论&#x1f48c; 目…

c++11~c++20 结构化绑定

结构化帮绑定可以作用于3中类型 一、原生数组类型 结果&#xff1a; 备注&#xff1a;绑定到原生数组所需条件仅仅是要求别名的数量于数组元素的个数一致&#xff0c;这里的x&#xff0c;y&#xff0c;z分别绑定到a[0],a[1],a[2] 二、绑定到结构体和类对象 结果&#xff1a;…

selenium测试框架快速搭建详解

一、介绍 Selenium目前主流的web自动化测试框架&#xff1b;支持多种编程语言Java、pythan、go、js等&#xff1b;selenium 提供一系列的api 供我们使用&#xff0c;因此在web测试时我们要点页面中的某一个按钮&#xff0c;那么我们只需要获取页面&#xff0c;然后根据id或者n…