1、项目中责任链模式实战
我们使用责任链模式实现对订单中参数的校验,首先校验订单id是否为空,然后校验下单人是否为空,最后检验收获地址是否为空。业务的流程图如下所示:
针对上述的业务,我们使用责任链的模式来实现这个功能:
(1)定义一个责任链的接口
java
public interface OrderCheckHandler {
/**
* 当前的订单检测实现逻辑
* @param orderCheckParam
*/
void check(OrderCheckParam orderCheckParam);
/**
* 设置下一个检测的实现逻辑
* @param nextOrderCheckHandler
* @return
*/
OrderCheckHandler setNext(OrderCheckHandler nextOrderCheckHandler);
}
(2)责任链中的公共逻辑的抽取
java
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)具体的检验逻辑(继承公共逻辑)
java
-- 订单id校验
public class OrderIdCheckHandler extends BaseCheckOrderHandler {
@Override
protected void currentCheck(OrderCheckParam orderCheckParam) {
if(orderCheckParam.getOrderId() == null){
throw new RuntimeException("订单id为空");
}
}
}
-- 用户校验
public class BuyerCheckHandler extends BaseCheckOrderHandler {
@Override
protected void currentCheck(OrderCheckParam orderCheckParam) {
if(orderCheckParam.getBuyer() == null){
throw new RuntimeException("用户不可以为空");
}
}
}
-- 地址校验
public class AddressCheckHandler extends BaseCheckOrderHandler {
@Override
protected void currentCheck(OrderCheckParam orderCheckParam) {
if(orderCheckParam.getAddress() == null){
throw new RuntimeException("用户地址不可以为空");
}
}
}
(4)使用spring将业务逻辑串联起来
java
@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调用责任链的
java
@Service
public class OrderService {
@Resource
private OrderCheckHandler orderCheckHandler;
public String checkOrderParam(OrderCheckParam param){
orderCheckHandler.check(param);
return "success";
}
}
(6)controller逻辑
java
@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审批、参数的校验、日志记录器链等等。