责任链模式二

本文以创建商品案例来讲解责任链模式,.假设创建商品逻辑分为: 1. 创建商品 2. 检验商品 3. 保存商品. 第二步中校验商品又分为多种情况,必填字段校验,规格校验,价格校验,库存校验等等.

伪代码如下:

public Result createProcuct(Product param){
        //参数校验
        Result paramCheck = this.paramCheck(param);
        if (!paramCheck.isSuccess()) {
            return paramCheck;
        }
        //价格校验
        Result priceCheck = this.priceCheck(param);
        if (!priceCheck.isSuccess()) {
            return priceCheck;
        }

        //库存校验
        Result stockCheck = this.stockCheck(param);
        if (!stockCheck.isSuccess()) {
            return stockCheck;
        }
        //.....
        //保存商品
        return this.saveProduct(param);
    }

以上代码看起来似乎没什么问题,但是随着公司业务需求不断增加,相关校验也会越来越多,新增功能就需要在原来代码上修改,使代码越来越臃肿,可维护性原来越差,校验不可以复用.下面我们使用责任链模式来优化,实现校验可以编排,动态扩展.

UML类图
uml

1. 创建商品参数对象
@Data
@Builder
public class Product {
    /**
     * 商品SKU(唯一)
     */
    private Long skuId;
    /**
     * 商品名称
     */
    private String skuName;
    /**
     * 商品图片路径
     */
    private String imgPath;
    /**
     * 价格
     */
    private BigDecimal price;
    /**
     * 库存
     */
    private Integer stock;
}
2. 抽象处理器
@Component
@Getter
@Setter
public abstract class AbstractCheckHandler {
    /**
     * 当前处理器持有的下一个处理器
     */
    protected AbstractCheckHandler nextHandler;
    /**
     * 处理器配置
     */
    protected ProductCheckHandlerConfig config;

    /**
     * 处理器执行方法
     * @param param
     * @return
     */
    public abstract Result handler(Product param);

    protected Result next(Product param) {
        //下一个链路为空,直接返回
        if (nextHandler == null) {
            return Result.success();
        }
        return nextHandler.handler(param);
    }
}
3. 处理器配置类
@AllArgsConstructor
@Data
public class ProductCheckHandlerConfig {
    /**
     * 处理器Bean名称
     */
    private String handler;
    /**
     * 下一个处理器
     */
    private ProductCheckHandlerConfig next;
    /**
     * 是否降级
     */
    private boolean down;
}
4. 创建抽象类子类,NullCheckHandler控制校验处理器,PriceChekcHandler价格校验处理器,StockCheckHandler库存校验处理器
@Component
public class NullCheckHandler extends AbstractCheckHandler{
    @Override
    public Result handler(Product param) {
        System.out.println("空值校验开始...");

        //降级:如果配置了降级,则跳过此处理器执行下一个处理器
        if(super.config.isDown()){
            System.out.println("空值校验降级通过");
            return super.next(param);
        }
        //校验逻辑
        if(param == null){
            return Result.failure("商品参数不能为空");
        }
        if(param.getSkuId() == null){
            return Result.failure("商品SKU不能为空");
        }
        //省略其它校验
        System.out.println("空值校验通过");
        return super.next(param);
    }
}
@Component
public class PriceCheckHandler extends AbstractCheckHandler{
    @Override
    public Result handler(Product param) {
        System.out.println("价格校验开始...");
        //降级:如果配置了降级,则跳过此处理器执行下一个处理器
        if(super.config.isDown()){
            System.out.println("价格校验降级通过");
            return super.next(param);
        }
        //非法价格校验
        if (param.getPrice().compareTo(BigDecimal.ZERO) <=0) {
            return Result.failure("价格非法");
        }

        //其它校验逻辑..

        //执行下一个处理器
        System.out.println("价格校验通过");
        return super.next(param);
    }
}

@Component
public class StockCheckHandler extends AbstractCheckHandler{
    @Override
    public Result handler(Product param) {
        System.out.println("库存校验开始...");
        //降级:如果配置了降级,则跳过此处理器执行下一个处理器
        if(super.config.isDown()){
            System.out.println("库存校验降级通过");
            return super.next(param);
        }
        if (param.getStock()<=0) {
            return Result.failure("库存已空");
        }
        System.out.println("库存校验通过");
        return super.next(param);
    }
}
5. 处理器执行链路类
public class HandlerClient {

    public static Result executeChain(AbstractCheckHandler handler, Product param){
        Result handlerResult = handler.handler(param);
        if (!handlerResult.isSuccess()) {
            System.out.println("责任链执行失败,返回: "+handlerResult.getMsg());
            return handlerResult;
        }

        return Result.success();
    }
}

6. 测试

@SpringBootTest
class ApplicationTests {

    @Autowired
    private Map<String, AbstractCheckHandler> handlerMap;

    @Test
    public void createProduct(){
        Product param = Product.builder().skuId(123L).price(new BigDecimal(50)).stock(1).build();
        Result paramCheckResult = this.paramCheck(param);

        if (!paramCheckResult.isSuccess()) {
            System.out.println(paramCheckResult.toString());
            return;
        }
        //执行保存商品

        System.out.println("成功");
    }

    /**
     * 使用责任链校验参数
     * @param param
     * @return
     */
    private Result paramCheck(Product param) {
        //模拟从配置中心获取配置检验链路
        String configJson = "{\"handler\":\"nullCheckHandler\",\"down\":true,\"next\":{\"handler\":\"priceCheckHandler\",\"next\":{\"handler\":\"stockCheckHandler\",\"next\":null}}}";
        //转成Config对象
        ProductCheckHandlerConfig handlerConfig = JSONUtil.toBean(configJson, ProductCheckHandlerConfig.class);

        AbstractCheckHandler handler = this.getHandler(handlerConfig);

        return HandlerClient.executeChain(handler,param);
    }

    /**
     * 获取处理器
     * @param config
     * @return
     */
    private AbstractCheckHandler getHandler(ProductCheckHandlerConfig config) {
        if (config == null) {
            return null;
        }
        //配置错误
        if (config.getHandler().isEmpty()) {
            return null;
        }
        //配置了不存在的处理器
        AbstractCheckHandler abstractCheckHandler = handlerMap.get(config.getHandler());
        if (abstractCheckHandler == null) {
            return null;
        }
        //处理器设置配置config
        abstractCheckHandler.setConfig(config);

        abstractCheckHandler.setNextHandler(this.getHandler(config.getNext()));

        return abstractCheckHandler;

    }

}

结果:
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值