职责链模式在表单验证中的应用

143 阅读2分钟
背景

常常在做像注册,条件搜索会做表单提交,但发请求前会做各种验证,要把规则验证完才能提交。

分析

大多数会在一个验证的方法里写很多if判断语句,判断不通过就return false, 判断通过就return true,让代码显得逻辑很乱。比如说这样:

    function check(form){
        // 时间需要满足的条件
        if(form.date){}
        
        // 地区需要满足的条件
        if(form.area){}
        
        // 还有不同规则组合需要满足的条件
        if(form.rules1 && form.rules2){}
    }

整个看下来这个方法非常臃肿,当然这个时候会改进一下,把不同规则的验证单独写一个方法,但还是会有一个不好的地方,那就是不能在某个规则不通过的条件下能及时退出这个方法,否则就只有在每个单独验证规则的方法后面再写一个判断是false还是true。

解决

这个时候可以考虑引入职责链模式,网上讨论职责链模式的文章有很多,比如说这篇
那现在换成职责链模式的做法

class Chain{
    constructor(fn) {
        this.fn = fn;
        this.successor = null;
    }
    setNext(successor) {
        return (this.successor = successor);
    }
    passRequest() {
        const res = this.fn.apply(this, arguments);
        if(res === 'nextSuccesor'){
            return this.successor && this.successor.passRequest.apply(this.successor, arguments);
        }
        return res;
    }
}

let checkDate = function(form) {
    if(pass){
        return true;
    }else {
        return  'nextSuccesor';
    }
}

let checkArea = function(form) {
    if(pass){
        return true;
    }else {
        return 'nextSuccesor';
    }
}

// 记得最后一个规则要返回true或者false
let checkRules1AndRules2 = function(form) {
    if(pass){
        return true;
    }else {
        return 'nextSuccesor';
    }
}
let checkDateChain = new Chain(checkDate);
let checkAreaChain = new Chain(checkArea);
let checkRules1AndRules2Chain = new Chain(checkRules1AndRules2);
// 按顺序验证规则
checkDateChain.setNext(checkAreaChain).setNext(checkRules1AndRules2Chain);
return checkDateChain.passRequest();

按这样写的方式就实现了低耦合,还可以按顺序,比如说有些规则是只要填了日期,其他的都不需要验证了,就可以放在最前面。脑子里也会有更清晰的顺序。