用责任链模式改造 if else

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

代码写着写着,if else if 逻辑忘记了,哎。。。-CSDN博客

责任链模式(Chain of Responsibility Pattern)

  1. 什么是责任链模式?

责任链模式是一种行为设计模式,它允许请求沿着处理者链传递,直到其中一个处理者处理它。每个处理者都可以决定是否处理请求或者将其传递给链中的下一个处理者。

  1. 责任链模式的优点

降低耦合度:请求发送者不需要知道请求的最终处理者是谁,只需要知道请求会被某个处理者处理。

灵活配置处理链:可以根据需要动态地增加或删除处理者,而不影响其他处理者。

增强系统扩展性:新的处理者可以很容易地添加到链中,从而扩展系统的功能。

  1. 责任链模式的应用场景

权限控制:多个权限检查器组成一个链,逐级检查用户的权限。

日志处理:多个日志处理器组成一个链,逐级处理日志消息。

支付处理:多种支付方式组成一个链,逐级处理支付请求。

  1. 责任链模式的实现

现在如下代码改成 责任链模式

java 复制代码
        //代理价>销售价
        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

java 复制代码
/**
 * @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;
    }
}

结果枚举类

java 复制代码
@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 属性是执行 下一个处理器
java 复制代码
@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
java 复制代码
public class AgentPriceGreaterThanGoodsPriceHandler extends PriceCheckHandler {

    @Override
    public void handle(PriceCheckRequest request) {
        if (BigDecimalUtil.isGreaterThan(request.getAgentPrice(),request.getGoodsPrice())) {
            request.setPriceCheckEnum(PriceCheckEnum.AGENT_PRICE_GREATER_THAN_SALE_PRICE);
        }
        check(request);
    }
}

供货价大于代理价处理器

复制代码
SupplyPriceGreaterThanAgentPriceHandler
java 复制代码
public class SupplyPriceGreaterThanAgentPriceHandler extends PriceCheckHandler {

    @Override
    public void handle(PriceCheckRequest request) {
        if (BigDecimalUtil.isGreaterThan( request.getSupplyPrice(), request.getAgentPrice())) {
            request.setPriceCheckEnum(PriceCheckEnum.SUPPLIER_PRICE_GREATER_THAN_AGENT_PRICE);
        }
        check(request);
    }
}
复制代码
(销售价-代理价)/代理价<5% 处理器
复制代码
AgentPricePercentageDifferenceHandler
java 复制代码
public class AgentPricePercentageDifferenceHandler extends PriceCheckHandler {

    @Override
    public 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 默认返回价格检查通过,需要把它放在责任链的最后处理器
java 复制代码
public class DefaultPriceHandler extends PriceCheckHandler {

    @Override
    public void handle(PriceCheckRequest request) {
        request.setPriceCheckEnum(PriceCheckEnum.DEFAULT);
    }
}

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

复制代码
ChainBuilder
java 复制代码
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);
        }
    }
}

最后测试

java 复制代码
@Slf4j
public class ChainBuilderTest {

    @Test
    public 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_PRICE
        priceCheckRequest = 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_PRICE
        priceCheckRequest = 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"));
        //DEFAULT
        priceCheckRequest = new PriceCheckRequest(product);
        ChainBuilder.chainBuilder.process(priceCheckRequest);
        log.info("商品价格校验结果:{}", JSONUtil.toJsonStr(priceCheckRequest) );
    }


}

输出结果,

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

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

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

相关推荐
xlsw_1 小时前
java全栈day20--Web后端实战(Mybatis基础2)
java·开发语言·mybatis
神仙别闹2 小时前
基于java的改良版超级玛丽小游戏
java
黄油饼卷咖喱鸡就味增汤拌孜然羊肉炒饭3 小时前
SpringBoot如何实现缓存预热?
java·spring boot·spring·缓存·程序员
暮湫3 小时前
泛型(2)
java
超爱吃士力架3 小时前
邀请逻辑
java·linux·后端
南宫生3 小时前
力扣-图论-17【算法学习day.67】
java·学习·算法·leetcode·图论
转码的小石3 小时前
12/21java基础
java
李小白663 小时前
Spring MVC(上)
java·spring·mvc
GoodStudyAndDayDayUp3 小时前
IDEA能够从mapper跳转到xml的插件
xml·java·intellij-idea
装不满的克莱因瓶4 小时前
【Redis经典面试题六】Redis的持久化机制是怎样的?
java·数据库·redis·持久化·aof·rdb