用责任链模式改造 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 放到倒数第二个,是可以延迟计算。

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

相关推荐
一只爱打拳的程序猿6 分钟前
【Spring】更加简单的将对象存入Spring中并使用
java·后端·spring
杨荧7 分钟前
【JAVA毕业设计】基于Vue和SpringBoot的服装商城系统学科竞赛管理系统
java·开发语言·vue.js·spring boot·spring cloud·java-ee·kafka
minDuck9 分钟前
ruoyi-vue集成tianai-captcha验证码
java·前端·vue.js
为将者,自当识天晓地。28 分钟前
c++多线程
java·开发语言
daqinzl36 分钟前
java获取机器ip、mac
java·mac·ip
激流丶1 小时前
【Kafka 实战】如何解决Kafka Topic数量过多带来的性能问题?
java·大数据·kafka·topic
Themberfue1 小时前
Java多线程详解⑤(全程干货!!!)线程安全问题 || 锁 || synchronized
java·开发语言·线程·多线程·synchronized·
让学习成为一种生活方式1 小时前
R包下载太慢安装中止的解决策略-R语言003
java·数据库·r语言
晨曦_子画1 小时前
编程语言之战:AI 之后的 Kotlin 与 Java
android·java·开发语言·人工智能·kotlin
南宫生2 小时前
贪心算法习题其三【力扣】【算法学习day.20】
java·数据结构·学习·算法·leetcode·贪心算法