在Spring中使用责任链模式

一、优缺点

优点:
降低了各个处理器之间的耦合,各处理器只关注处理自身的内部逻辑,然后抛给下一个处理器即可。
不需要关注具体的上下游调用关系,在组装责任链时通过spring的特性动态注入下一个处理器的调用关系。
通过@Order注解,可灵活调整各处理器之间的调用顺序

缺点:
会增加程序的复杂度,需评估酌情使用,不可为了设计模式而用设计模式。

二、使用

1. 定义业务用到的基础类

import java.io.Serializable;
 
/**
 * @author lishuzhen
 * @createTime 2022年06月19日 22:40:00
 */
public class ResultDTO implements Serializable {
    private String msg;
 
    public static ResultDTO ok(){
        return new ResultDTO();
    }
 
    public ResultDTO() {
        msg = "ok";
    }
 
    public String getMsg() {
        return msg;
    }
}
 
 
/**
 * @author lishuzhen
 * @createTime 2022年06月19日 22:15:00
 */
public class OrderDTO {
    private String orderNo;
 
    public String getOrderNo() {
        return orderNo;
    }
 
    public void setOrderNo(String orderNo) {
        this.orderNo = orderNo;
    }
}

2. 定义抽象的处理器接口

定义doFilter方法,由子类实现处理器的内部逻辑,注意在doFilter方法的最后一步要记得调用doNextFilter()
定义doNextFilter方法,由抽象类完成调用下一个处理器的代码。

/**
 * 处理器抽象类
 *
 * @author lishuzhen
 * @createTime 2022年06月19日 22:52:00
 */
public abstract class AbstractOrderChainHandler {
 
    private AbstractOrderChainHandler nextHandler;
 
    /**
     * 执行过滤方法
     *
     * @param orderDTO
     * @return
     */
    abstract protected ResultDTO doFilter(OrderDTO orderDTO);
 
    /**
     * 执行下一个处理器
     *
     * @param orderDTO
     * @param resultDTO
     * @return
     */
    protected ResultDTO doNextHandler(OrderDTO orderDTO, ResultDTO resultDTO) {
        if (nextHandler == null) {
            return resultDTO;
        }
        return nextHandler.doFilter(orderDTO);
    }
 
    public void setNextHandler(AbstractOrderChainHandler nextHandler) {
        this.nextHandler = nextHandler;
    }
}

3. 定义处理器的子类实现

必须实现抽象的处理器接口,供容器启动时获取所有的处理器实现类
通过@Order注解,标识当前处理器在整个责任链中的位置。建议区间设置的大一些,后续增加处理器时比较方便。

/**
 * 订单提交-库存计算处理器
 *
 * @author lishuzhen
 * @createTime 2022年06月19日 22:57:00
 */
@Service
@Order(100)
public class StockOrderChainHandler extends AbstractOrderChainHandler {
    /**
     * 执行过滤方法
     *
     * @param orderDTO
     * @return
     */
    @Override
    protected ResultDTO doFilter(OrderDTO orderDTO) {
        System.out.println("库存计算处理");
        return doNextHandler(orderDTO, ResultDTO.ok());
    }
}
/**
 * 订单提交-价格计算处理器
 *
 * @author lishuzhen
 * @createTime 2022年06月19日 22:59:00
 */
@Service
@Order(300)
public class PriceOrderChainHandler extends AbstractOrderChainHandler {
    /**
     * 执行过滤方法
     *
     * @param orderDTO
     * @return
     */
    @Override
    protected ResultDTO doFilter(OrderDTO orderDTO) {
        System.out.println("价格计算处理");
        return doNextHandler(orderDTO, ResultDTO.ok());
    }
}
/**
 * 订单提交-优惠券计算处理器
 *
 * @author lishuzhen
 * @createTime 2022年06月19日 22:59:00
 */
@Service
@Order(200)
public class CouponOrderChainHandler extends AbstractOrderChainHandler {
    /**
     * 执行过滤方法
     *
     * @param orderDTO
     * @return
     */
    @Override
    protected ResultDTO doFilter(OrderDTO orderDTO) {
        System.out.println("优惠券处理");
        return doNextHandler(orderDTO, ResultDTO.ok());
    }
}

4. 封装组合责任链

通过@Autowired修饰责任链(处理器的集合),spring容器会按照@order的顺序组装一个有序的list集合。
通过@PostConstruct修饰constructChain()方法,使容器回调此方法,完成为每一个处理设置它的下一个处理器
定义firstHandler,表示这是当前责任链路顶端的第一个处理器。

/**
 * 订单处理责任链
 *
 * @author lishuzhen
 * @createTime 2022年06月19日 23:05:00
 */
@Service
public class OrderChainHandler {
 
    @Autowired
    private List<AbstractOrderChainHandler> chain;
 
    private AbstractOrderChainHandler firstHandler;
 
 
    @PostConstruct
    private void constructChain() {
        if (chain == null || chain.size() == 0) {
            throw new RuntimeException("not found order chain handler");
        }
        firstHandler = chain.get(0);
        for (int i = 0; i < chain.size(); i++) {
            if (i == chain.size() - 1) {
                chain.get(i).setNextHandler(null);
            } else {
                chain.get(i).setNextHandler(chain.get(i + 1));
            }
        }
    }
 
    public ResultDTO executionChain(OrderDTO orderDTO) {
        return firstHandler.doFilter(orderDTO);
    }
}

5. 写一个测试接口

@Controller
@RequestMapping("/lsz")
public class OrderTestController {
 
    @Autowired
    private OrderChainHandler orderChainHandler;
 
 
    @ResponseBody
    @RequestMapping("testOrder")
    public Object testOrder(String orderNo){
        return orderChainHandler.executionChain(new OrderDTO()).getMsg();
    }
}

你可能感兴趣的:(spring,责任链模式,java)