太优雅了,责任链模式在项目中的实战应用

现实生活中铁链,它由一个个铁环首尾相接构成一条完成的链子,如下图所示:

类比到责任链模式中,铁链中的每个节点可以看成责任链模式中的每个对象,然后每个对象负责处理单一的逻辑。将一个请求从链首端发出,沿着链的路径依次传递到每个节点上处理逻辑,直到所有的对象处理完成这个请求为止,这种设计模式称为责任链模式。

1、项目中责任链模式实战

我们使用责任链模式实现对订单中参数的校验,首先校验订单di是否为空,然后校验下单人是否为空,最后检验收获地址是否为空。业务的流程图如下所示:

针对上述的业务,我们使用责任链的模式来实现这个功能,如下是项目的工程结构图:

(1)定义一个责任链的接口

public interface OrderCheckHandler { 
    /** 
     * 当前的订单检测实现逻辑 
     * 
     */ 
    void check(OrderCheckParam orderCheckParam); 
    /** 
     * 设置下一个检测的实现逻辑 
     * 
     */ 
    OrderCheckHandler setNext(OrderCheckHandler nextOrderCheckHandler); 
}

(2)责任链中的公共逻辑的抽取

public abstract class BaseCheckOrderHandler implements OrderCheckHandler { 
    private OrderCheckHandler nextOrderCheckHandler; 
    @Override 
    public void check(OrderCheckParam orderCheckParam) { 
        this.currentCheck(orderCheckParam); 
        if(Objects.nonNull(nextOrderCheckHandler)){ 
            nextOrderCheckHandler.check(orderCheckParam); 
        } 
    } 
    /** 
     * 具体的实现逻辑 
     * 
     */ 
    protected abstract void currentCheck(OrderCheckParam orderCheckParam); 
    @Override 
    public OrderCheckHandler setNext(OrderCheckHandler nextOrderCheckHandler) { 
        this.nextOrderCheckHandler = nextOrderCheckHandler; 
        return this.nextOrderCheckHandler; 
    } 
}

(3)具体的检验逻辑(继承公共逻辑)

--------------------订单id校验逻辑--------------------------- 
@Service 
public class OrderIdCheckHandler extends BaseCheckOrderHandler { 
    @Override 
    protected void currentCheck(OrderCheckParam orderCheckParam) { 
        if(orderCheckParam.getOrderId() == null){ 
            throw new RuntimeException("订单id为空"); 
        } 
    } 
} 
--------------------用户校验逻辑--------------------------- 
@Service 
public class BuyerCheckHandler extends BaseCheckOrderHandler { 
    @Override 
    protected void currentCheck(OrderCheckParam orderCheckParam) { 
        if(orderCheckParam.getBuyer() == null){ 
            throw new RuntimeException("用户不可以为空"); 
        } 
    } 
} 
--------------------收货地址的校验逻辑------------------------- 
@Service 
public class AddressCheckHandler extends BaseCheckOrderHandler { 
    @Override 
    protected void currentCheck(OrderCheckParam orderCheckParam) { 
        if(orderCheckParam.getAddress() == null){ 
            throw new RuntimeException("用户地址不可以为空"); 
        } 
    } 
}

(4)使用spring将业务逻辑串联起来

@Configuration 
public class OrderCheckConfig { 
    @Bean 
    public BuyerCheckHandler buyerCheckHandler(){ 
        return new BuyerCheckHandler(); 
    } 
    @Bean 
    public OrderIdCheckHandler checkOrderIdHandler(){ 
        return new OrderIdCheckHandler(); 
    } 
    @Bean 
    public AddressCheckHandler addressCheckHandler(){ 
        return new AddressCheckHandler(); 
    } 
    //设置责任链得执行链路顺序 
    @Bean 
    public OrderCheckHandler orderCheckHandler(){ 
        OrderIdCheckHandler orderIdCheckHandler = this.checkOrderIdHandler(); 
        orderIdCheckHandler.setNext(this.buyerCheckHandler()).setNext(this.addressCheckHandler()); 
        return orderIdCheckHandler; 
    } 
}

(5)service调用责任链的

@Service 
public class OrderService { 
    @Resource 
    private OrderCheckHandler orderCheckHandler; 
    public String checkOrderParam(OrderCheckParam param){ 
        orderCheckHandler.check(param); 
        return "success"; 
    } 
}

(6)controller逻辑

@RestController 
@RequestMapping("/test") 
public class ZeRenLianTestController { 
    @Resource 
    private OrderService orderService; 
    @GetMapping("/checkOrder") 
    public String checkOrder(){ 
        OrderCheckParam orderCheckParam = new OrderCheckParam(); 
        orderCheckParam.setAddress("123"); 
        orderCheckParam.setOrderId("1235689"); 
        return orderService.checkOrderParam(orderCheckParam); 
    } 
}

测试结果图:

如果现在需要增加一种校验(如增加订单物流的校验),此时我们只需要增加一个业务的实现类,然后在spring的配置将这个业务实现类加入到责任链逻辑上就可以了。

总结:

(1)需要保证责任链的结构清晰、避免创建过长的链,进而提升执行的性能。

(2)每个业务应该具有单一职责,每个对象专注于处理自己的逻辑。

(3)责任链模式使用的典型场景是多个对象处理同一个请求,如OA审批、参数的校验、日志记录器链等等。

1