责任链模式-运用责任链模式优化多层校验

1.背景

项目的背景这样的。有一个导入接口,用户可以通过Excel导入的方式,导入一份Excel文件。文件里面的内容有多列,有些列必须进行参数的校验是否符合规则。大概的任务流程模式如下:
在这里插入图片描述

2.常规设计思路

根据上面的流程图,我们很容易就联想到,可以将这个几个方法封装成一个个校验方法,然后一个个调用。伪代码如下:

public class ChainDemo {
    
    public static void main(String[] args) {
        CheckObject checkObject = new CheckObject();
        ChainDemo chainDemo = new ChainDemo();
        chainDemo.checkOrg(checkObject);
        chainDemo.checkOrg(checkObject);
        chainDemo.checkEmployeeId(checkObject);
        chainDemo.checkPhone(checkObject);
        chainDemo.checkAccount(checkObject);
    }
    
    private void checkOrg(CheckObject checkObject) {
    
    }
    
    private void checkPost(CheckObject checkObject) {
    
    }
    
    private void checkEmployeeId(CheckObject checkObject) {
    
    }
    
    private void checkPhone(CheckObject checkObject) {
    
    }
    
    private void checkAccount(CheckObject checkObject) {
    
    }
}

}

大家应该可以从上面看出来,如果我们后续要校验其他属性,比如说要校验员工的身份证是否符合规则等。就是不断地添加private方法。这样会带来以下缺点:

  1. 因为是private方法,因此在Demo类里面的逻辑会越来越多,显得臃肿;
  2. 缺乏扩展性,诚然我们可以再加一个private方法,但是我们已经修改到了Main方法内部。

3.运用责任链设计模式改造

从上面其实我们可以分析出是一个checkObject,不断在内部传递验证,这就好比我们平时写代码的时候那些校验链一样。这个时候我们就可以用责任链模式封装起来。
责任链模式有三大要素:

  1. chain的调用类;
  2. 方法调用封装的接口;
  3. 每一个链上节点自己的实现;

在这里插入图片描述

public interface IHandler {
  boolean handle();
}

public class HandlerA implements IHandler {
  @Override
  public boolean handle() {
    boolean handled = false;
    //...
    return handled;
  }
}

public class HandlerB implements IHandler {
  @Override
  public boolean handle() {
    boolean handled = false;
    //...
    return handled;
  }
}

public class HandlerChain {
  private List<IHandler> handlers = new ArrayList<>();

  public void addHandler(IHandler handler) {
    this.handlers.add(handler);
  }

  public void handle() {
    for (IHandler handler : handlers) {
      boolean handled = handler.handle();
      if (handled) {
        break;
      }
    }
  }
}

// Main方法
public class Application {
  public static void main(String[] args) {
    HandlerChain chain = new HandlerChain();
    chain.addHandler(new HandlerA());
    chain.addHandler(new HandlerB());
    chain.handle();
  }
}

4.项目中的实际案例

从第三点我们知道了基本的使用。但是我们现在一般Java项目和Spring分不开,实际应用还得和Spring结合起来。

4.1 定义通用接口
public interface IBatchUserInfoCheckHandler {
    
    
    /**
     * 处理校验请求
     * @param checkUserBatchInfoDTO 参数
     * @return 返回是否校验成功
     */
    void handle(CheckUserBatchInfoDTO checkUserBatchInfoDTO);
4.1 在链中传递的封装类
public class CheckUserBatchInfoDTO {
	// 各种属性
}
4.2 实现IBatchUserInfoCheckHandler 的各种Handler

由于都是大同小异,因此这里只列出几个实现的接口


@Service
// @Order 注解可以让我们控制注入的顺序,1就代表第一个1,优先级最高
@Order(1)
public class CheckOrgHandler implements IBatchUserInfoCheckHandler {

	@Override
    public void handle(CheckUserBatchInfoDTO checkUserBatchInfoDTO) {
    		// 处理校验组织架构
	}
}

@Service
@Order(2)
public class CheckPositionHandler implements IBatchUserInfoCheckHandler{
	@Override
    public void handle(CheckUserBatchInfoDTO checkUserBatchInfoDTO) {
    		// 处理校验岗位的逻辑
	}
}

4.3 一个Chain类
@Component
@Slf4j
public class BatchUserInfoCheckHandlerChain {

	// Spring会找到所有实现了IBatchUserInfoCheckHandler接口的handler依次注入
    @Autowired
    private List<IBatchUserInfoCheckHandler> handlerList;

    public void handle(CheckUserBatchInfoDTO checkUserBatchInfoDTO) {
        if (CollectionUtils.isNotEmpty(handlerList)) {
            for (IBatchUserInfoCheckHandler handler : handlerList) {
                handler.handle(checkUserBatchInfoDTO);
            }
        }
    }
}
4.4 依赖注入使用
@Service
public class TestService {
	@Resource
	private BatchUserInfoCheckHandlerChain  chain;	

	public void checkValue() {
			CheckUserBatchInfoDTO  checkObject = new CheckUserBatchInfoDTO ();
			chain.handle(checkObject );
	}
}

从上面的时候我们可以看出,如果我们后面想要扩展的话,非常的简单,只需要新建一个类实现IBatchUserInfoCheckHandler,设置好@Order的顺序,以前调用的地方完全不用改。非常符合设计原则。假设以后我们需要修改以前的代码,比如说校验组织架构的逻辑改了,我们直接就可以在CheckOrgHandler里面进行修改,并不影响以前的调用方式。

结语

如果我们项目中存在这种需要链式调用的,我们不妨使用上责任链模式优化一把,可以使我们的代码符合设计原则,让代码看上去更简洁。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值