策略模式学习

72 阅读2分钟

前段时间在完成公司项目中,需要给一个输入框写一个校验规则,其中包括字符长度校验、特殊字符校验、邮箱格式校验、每行是否重复的校验等。于是机智如我,写出一段类似下面的这种代码:

function validation() {
    let juegeLength = 0;
    let judgeRegex = 0;
    let judgeEmail = 0;
    let judgeRepeat = 0;
    for (let keyword of keywords) {
         if (keyword.length > maxLength || keyword.length < minLength) {
             juegeLength = 1;
         }
         if (......) {
             judgeRegex = 1;
         }
         if (......) {
             judgeEmail = 1;
         }
         if (......) {
             judgeRepeat = 1;
         }
         if......
    }
 
    if (juegeLength) {
        return '不符合长度校验';
    } else if (judgeRegex) {
        return '不符合特殊字符校验';
    } else if (validateEmail) {
        return '不符合邮箱格式校验';
    } else if (validateRepeat) {
        return '不符合每行不重复校验';
    } else if ...
    
    return true; 
}

是不是很简单,清晰明了啊。然而,如果有业务发展或者需求变更,整个代码就需要再次修改,其维护性就特别差。当需求很多的时候,比如需要几十个不同的校验规则,按照上面的方式就要写上个几十个if语句,这样代码十分臃肿,可读性也是极差。而这种情况又被叫做if/else嵌套地狱,试想你看到一个函数里面几十个if/else语句嵌套,编辑器滑了一页又一页却还在if/else中,是不是轻则头痛欲喷,重则当场吐血卒之呢。反正当我把这种代码给我导师审核时,被他笑骂,“丑陋之。”

那就优化呗。机智又如我,把每个校验函数提取出来,后面就可以进行复用了,然后真正要使用到的时候,就直接一个调用。前面可以直接return的也直接return出去,后面使用变量判断也完全没有必要了。完美~ 于是,我的代码优化如下:

function validation() {
    for (let keyword of keywords) {
         validateLength();
         validateRegex();
         validateEmail();
         validateRepeat();
         ......
    }
 
    return true;
}

多简洁啊,然而这与前面的“地狱”只是换汤不换药,并不能改变其本质。在我导师的建议下,采用策略模式来解决这种问题。首先,上定义:

策略模式,指的是定义一系列算法,将每一个算法封装起来,并让它们可以相互替换。策略模式让算法独立于使用它的客户而变化。

最终,我的代码如下形式:

function validation() {
    let strategys = [validateLength, validateRegex, validateEmail, validateRepeat];
    for (let strategy of strategys) {
        strategy();
    }
    return true;
}

当又有新的校验时,直接在strategys里面push校验规则即可,而不用去修改代码的逻辑。

菜鸡一枚,纯当学习记录,如有不对,敬请指正。