工作中常用到的设计模式-业务校验的设计

一、概述

工作中比较常见的业务场景,比如对外提供一个数据上传接口,基本的业务逻辑,一般都有参数非空校验、安全校验(比如IP、非正常请求等)、黑白名单校验、规则拦截等等。很多开发伙伴会使用异常来实现。

public class Upload{

    public void checkNullParam(Object param){
      //参数非空校验
      throw new RuntimeException();
    }
    public void checkSecurity(){
      //安全校验
      throw new RuntimeException();
    }
    public void checkBackList(){
        //黑名单校验
        throw new RuntimeException();
    }
    public void checkRule(){
        //规则拦截
        throw new RuntimeException();
    }
}

二、业务校验的设计

上面的示例代码使用了异常来做逻辑条件判断,如果后续逻辑越来越复杂的话,会出现一些问题:如异常只能返回异常信息,不能返回更多的字段,这时候需要自定义异常类。而且异常的处理效率比条件判断方式要低很多。

阿里开发手册规定:禁止用异常做逻辑判断 ,这里可以考虑责任链模式。

责任链模式:将处理不同逻辑的对象连接成一个链表结构,每个对象都保存下一个节点的引用:

  • 一个接口或者抽象类
  • 每个对象差异化处理
  • 对象链(数组)初始化(连起来)

2.1 一个接口或者抽象类

  • 有一个指向责任下一个对象的属性
  • 一个设置下一个对象的set方法
  • 给子类对象差异化实现的方法(如代码中的doFilter方法)
public abstract class AbstractHandler {

    //责任链中的下一个对象
    private AbstractHandler nextHandler;

    /**
     * 责任链的下一个对象
     */
    public void setNextHandler(AbstractHandler nextHandler){
        this.nextHandler = nextHandler;
    }
    
    public AbstractHandler getNextHandler() {
        return nextHandler;
    }


    /**
     * 具体参数拦截逻辑,给子类去实现
     */
    public void filter(Request request, Response response) {
        doFilter(request, response);
        if (getNextHandler() != null) {
            getNextHandler().filter(request, response);
        }
    }


    /**
     * 子类对象差异化实现的方法
     */
    abstract void doFilter(Request filterRequest, Response response);

}

2.2 每个对象差异化处理

/**
 * 参数校验对象
 **/
@Component
@Order(1) //顺序排第1,最先校验
public class CheckParamFilterObject extends AbstractHandler {

    @Override
    public void doFilter(Request request, Response response) {
        System.out.println("非空参数检查");
    }
}
/**
 *  黑名单校验对象
 */
@Component
@Order(2) //校验顺序排第2
public class CheckBlackFilterObject extends AbstractHandler {

    @Override
    public void doFilter(Request request, Response response) {
        //校验黑名单
        System.out.println("校验黑名单");
    }
}
/**
 *  规则拦截对象
 */
@Component
@Order(3) //校验顺序排第3
public class CheckRuleFilterObject extends AbstractHandler {

    @Override
    public void doFilter(Request request, Response response) {
        //check rule
        System.out.println("check rule");
    }
}

2.3 对象链初始化(责任链连起来)&& 使用

@Component("ChainPatternDemo")
public class ChainPatternDemo {

    //自动注入各个责任链的对象
    @Autowired
    private List<AbstractHandler> abstractHandleList;

    private AbstractHandler abstractHandler;

    //spring注入后自动执行,责任链的对象连接起来
    @PostConstruct
    public void initializeChainFilter(){

        for(int i = 0;i<abstractHandleList.size();i++){
            if(i == 0){
                //责任链的第一个节点
                abstractHandler = abstractHandleList.get(0);
            }else{
                //责任链的对象连接起来
                AbstractHandler currentHander = abstractHandleList.get(i - 1);
                AbstractHandler nextHander = abstractHandleList.get(i);
                currentHander.setNextHandler(nextHander);
            }
        }
    }

    //使用---直接调用exec
    public Response exec(Request request, Response response) {
        abstractHandler.filter(request, response);
        return response;
    }

    public AbstractHandler getAbstractHandler() {
        return abstractHandler;
    }

    public void setAbstractHandler(AbstractHandler abstractHandler) {
        this.abstractHandler = abstractHandler;
    }
}

三、责任链总结

优点:

  • 1 将请求与处理解耦。
  • 2 请求处理者将不是自己职责范围内的请求,转发给下一个节点。
  • 3 请求发送者不需要关系链路结构,只需等待请求处理结果即可。
  • 4 链路结构灵活,易于扩展新的请求处理节点

缺点:

  • 责任链太长或者处理时间过长,会影响整体性能。
  • 如果节点对象存在循环引用,则会造成死循环,导致程序崩溃。

我目前的项目中,业务校验是把doFilter() 返回值优化成 Boolean类型,然后在filter() 方法中判断为true才继续往下调用,这样可以提升整体的性能。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值