前段时间在完成公司项目中,需要给一个输入框写一个校验规则,其中包括字符长度校验、特殊字符校验、邮箱格式校验、每行是否重复的校验等。于是机智如我,写出一段类似下面的这种代码:
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校验规则即可,而不用去修改代码的逻辑。
菜鸡一枚,纯当学习记录,如有不对,敬请指正。