我的上一篇文章,因为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 放到倒数第二个,是可以延迟计算。
还可以再在处理类处理了请求的时候,将处理次数加一进行统计,经过一段时间,用定时任务统计每个处理器的次数,将次数多的处理器动态调整放到前面。