责任链模式

责任链模式(Chain of Responsibility)是一种行为设计模式,它允许将请求沿着处理者链进行传递,直到有一个处理者处理它为止。该模式的主要目的是解耦请求的发送者和接收者,使多个对象都有机会处理这个请求,而不需要明确指定哪个对象处理请求。

在Java中,责任链模式通常涉及以下几个部分:

抽象处理者(Handler):定义一个处理请求的接口,通常包括一个处理请求的方法和一个设置下一个处理者的方法。

具体处理者(ConcreteHandler):实现抽象处理者接口的类。每个具体处理者可以处理一部分请求,如果不能处理,则将请求传递给下一个处理者。

客户端(Client):创建处理链并将请求发送到链的起始处理者。

++show my code ++

++show my code++

我的代码场景是,实现下单功能前的一系列校验操作,当所有检验条件都满足时才能够完成下单。

抽象处理者(Handler)

这里先创建一个 抽象处理者(Handler) 的接口,因为现在都是spring boot项目,肯定要有接口,供后续调用使用。

java 复制代码
/**
 * 订单校验的接口
 *
 */
public interface OrderCreateValidator {
    /**
     * 设置下一个校验器
     *
     * @param nextValidator
     */
    public void setNext(OrderCreateValidator nextValidator);

    /**
     * 返回下一个校验器
     *
     * @return
     */
    public OrderCreateValidator getNext();

    /**
     * 校验
     *
     * @param request
     * @throws OrderException 订单异常
     */
    public void validate(OrderCreateRequest request) throws OrderException;
}

这里定义上面的接口的抽象类,也就是:抽象处理者(Handler)

java 复制代码
/**
 * 订单校验的 抽象处理者(Handler)
 */
public abstract class BaseOrderCreateValidator implements OrderCreateValidator {

    protected OrderCreateValidator nextValidator;

    @Override
    public void setNext(OrderCreateValidator nextValidator) {
        this.nextValidator = nextValidator;
    }

    @Override
    public OrderCreateValidator getNext() {
        return nextValidator;
    }

    /**
     * 校验
     *
     * @param request
     * @throws Exception
     */
    @Override
    public void validate(OrderCreateRequest request) throws OrderException {
        doValidate(request);

        if (nextValidator != null) {
            nextValidator.validate(request);
        }
    }

    /**
     * 校验方法的具体实现
     *
     * @param request
     * @throws OrderException
     */
    protected abstract void doValidate(OrderCreateRequest request) throws OrderException;
}

具体处理者(ConcreteHandler)

创建具体的实现类,实现上面的抽象接口。

我们主要有三个具体实现,分别是商品校验、库存校验、用户校验。

java 复制代码
/**
 * 商品校验器
 */
@Component
public class GoodsValidator extends BaseOrderCreateValidator {

    @Autowired
    private GoodsFacadeService goodsFacadeService;

    @Override
    protected void doValidate(OrderCreateRequest request) throws OrderException {
        // 获取商品信息
        BaseGoodsVO baseGoodsVO = goodsFacadeService.getGoods(request.getGoodsId(), request.getGoodsType());

        if (!baseGoodsVO.available()) {
            throw new OrderException(GOODS_NOT_AVAILABLE);
        }

        if (baseGoodsVO.getPrice().compareTo(request.getItemPrice()) != 0) {
            throw new OrderException(GOODS_PRICE_CHANGED);
        }
    }
}
java 复制代码
/**
 * 库存校验器
 */
@Component
public class StockValidator extends BaseOrderCreateValidator {

    @Autowired
    private InventoryWrapperService inventoryWrapperService;

    @Override
    public void doValidate(OrderCreateRequest request) throws OrderException {
        // 获取库存信息
        BaseGoodsInventoryVO goodsInventoryVO = inventoryWrapperService.queryInventory(request);

        if (goodsInventoryVO == null) {
            throw new OrderException(INVENTORY_NOT_ENOUGH);
        }

        if (goodsInventoryVO.getInventory() == 0) {
            throw new OrderException(INVENTORY_NOT_ENOUGH);
        }

        if (goodsInventoryVO.getQuantity() < request.getItemCount()) {
            throw new OrderException(INVENTORY_NOT_ENOUGH);
        }

        if (goodsInventoryVO.getInventory() < request.getItemCount()) {
            throw new OrderException(INVENTORY_NOT_ENOUGH);
        }
    }
}
java 复制代码
/**
 * 用户校验器
 */
@Component
public class UserValidator extends BaseOrderCreateValidator {

    @Autowired
    private UserFacadeService userFacadeService;

    @Override
    public void doValidate(OrderCreateRequest request) throws OrderException {
        String buyerId = request.getBuyerId();
        UserQueryRequest userQueryRequest = new UserQueryRequest(Long.valueOf(buyerId));
        // 查询用户信息
        UserQueryResponse<UserInfo> userQueryResponse = userFacadeService.query(userQueryRequest);
        if (userQueryResponse.getSuccess() && userQueryResponse.getData() != null) {
            UserInfo userInfo = userQueryResponse.getData();
            if (userInfo.getUserRole() != null && !userInfo.getUserRole().equals(UserRole.CUSTOMER)) {
                throw new OrderException(BUYER_IS_PLATFORM_USER);
            }
            //判断买家状态
            if (userInfo.getState() != null && !userInfo.getState().equals(UserStateEnum.ACTIVE.name())) {
                throw new OrderException(BUYER_STATUS_ABNORMAL);
            }
            //判断买家状态
            if (userInfo.getState() != null && !userInfo.getCertification()) {
                throw new OrderException(BUYER_NOT_AUTH);
            }
        }
    }
}

到目前我们每个节点创建好了,接下来就是把这些节点串联起来,就形成了链------责任链模式。

客户端(Client)

配置spring boot的启动配置类,在项目启动时,形成责任链。

java 复制代码
/**
 * 订单创建校验器配置 (责任链模式)
 */
@Configuration
public class OrderCreateValidatorConfig {

    @Autowired
    private StockValidator stockValidator;

    @Autowired
    private GoodsValidator goodsValidator;

    @Autowired
    private UserValidator userValidator;

    // 启动时,注册这个责任链的开始链bean,不然无法找到到底应该使用哪一个
    @Bean
    public OrderCreateValidator orderValidatorChain() {
        // 用户校验器的下一个节点是商品校验器
        userValidator.setNext(goodsValidator);
        // 商品校验器的下一个节点是库存校验器
        goodsValidator.setNext(stockValidator);
        // 返回用户校验器,说明从责任链从用户校验器开始
        return userValidator;
    }
}

上面, 我们使用@Bean注册了OrderCreateValidator ,所有在调用时,直接注入这个bean,就可以使用这个完整的责任链啦。

java 复制代码
    @Autowired
    private OrderCreateValidator orderValidatorChain;
	
    @Override
    public OrderResponse create(OrderCreateRequest request) {
        try {
	    // 这里调用我们的责任链
            orderValidatorChain.validate(request);
        } catch (OrderException e) {
            return new OrderResponse.OrderResponseBuilder().buildFail(ORDER_CREATE_VALID_FAILED.getCode(), e.getErrorCode().getMessage());
        }

        Boolean preDeductResult = inventoryWrapperService.preDeduct(request);
        if (preDeductResult) {
            return orderService.create(request);
        }
        throw new OrderException(OrderErrorCode.INVENTORY_DEDUCT_FAILED);
    }

这样,一个责任链模式就完成了,我们只要调用责任链的开始就可以了, 不再需要关系责任链里到底经过了多少节点,节点怎么排列,都做了什么。这符合java的封装特性。

而且当我们后续想要再增加新的校验时,也非常方便,直接在责任链中添加新的校验器节点就可以了,而无需再修改业务逻辑代码。

非常好用,优雅!

相关推荐
逻各斯1 分钟前
redis中的Lua脚本,redis的事务机制
java·redis·lua
计算机毕设指导63 分钟前
基于Springboot学生宿舍水电信息管理系统【附源码】
java·spring boot·后端·mysql·spring·tomcat·maven
计算机-秋大田11 分钟前
基于Spring Boot的兴顺物流管理系统设计与实现(LW+源码+讲解)
java·vue.js·spring boot·后端·spring·课程设计
计算机小白一个22 分钟前
蓝桥杯 Java B 组之背包问题、最长递增子序列(LIS)
java·数据结构·蓝桥杯
m0_528723811 小时前
HTML中,title和h1标签的区别是什么?
前端·html
Dark_programmer1 小时前
html - - - - - modal弹窗出现时,页面怎么能限制滚动
前端·html
二十雨辰1 小时前
[Java基础]网络编程
java·开发语言
ACGkaka_1 小时前
抓包工具(三)Wireshark代理抓包Java程序的HTTPS请求
java·https·wireshark
GDAL1 小时前
HTML Canvas clip 深入全面讲解
前端·javascript·canvas
禾苗种树1 小时前
在 Vue 3 中使用 ECharts 制作多 Y 轴折线图时,若希望 **Y 轴颜色自动匹配折线颜色**且无需手动干预,可以通过以下步骤实现:
前端·vue.js·echarts