JavaScript设计模式之策略模式实现原理详解
俗话说,条条大路通罗马。在现实生活中,我们可以采用很多方法实现同一个目标。比如我们先定个小目标,先挣它一个亿。我们可以根据具体的实际情况来完成这个目标。
策略模式的定义
定义一系列的算法,把它们一个个封装起来,并且使它们可以相互替换。
举个例子:表单校验
在一个Web项目中,注册、登录等功能的实现都离不开表单提交。表单校验也是前端常常需要做的事。假设我们正在编写一个注册的页面,在点击提交按钮之前,有如下几条校验逻辑:
- 用户名不可为空,不允许以空白字符命名,用户名长度不能小于2位。
- 密码长度不能小于6位。
- 正确的手机号码格式。
也许,一开始我们会这么写:
策略模式-校验表单 用户名: 密码: 手机号码: 提交 varregisterForm=document.getElementById('registerForm'); registerForm.onsubmit=function(){ if(registerForm.userName.value===''){ alert('用户名不可为空'); returnfalse; } if(registerForm.userName.value===''){ alert('用户名不可为空'); returnfalse; } if(registerForm.userName.value.trim()===''){ alert('用户名不允许以空白字符命名'); returnfalse; } if(registerForm.userName.value.trim().length<2){ alert('用户名用户名长度不能小于2位'); returnfalse; } if(registerForm.password.value.trim().length<6){ alert('密码长度不能小于6位'); returnfalse; } if(!/^(13[0-9]|14[5|7]|15[0|1|2|3|5|6|7|8|9]|17[7]|18[0|1|2|3|5|6|7|8|9])\d{8}$/.test(registerForm.phoneNumber.value)){ alert('请输入正确的手机号码格式'); returnerrorMsg; } }
这是一种很常见的编码方式,但它有很明显的缺点:
- registerForm.onsubmit函数比较庞大,包含了很多if语句,这些语句要覆盖所有的校验规则。
- 若校验规则有变,不得不深入到registerForm.onsubmit函数的内部实现,违反开放-封闭原则。
- 算法的复用性差。
下面,让我们来用策略模式重构表单校验
策略模式:表单校验
策略模式-校验表单 用户名: 密码: 手机号码: 提交 //策略对象 varstrategies={ isNoEmpty:function(value,errorMsg){ if(value===''){ returnerrorMsg; } }, isNoSpace:function(value,errorMsg){ if(value.trim()===''){ returnerrorMsg; } }, minLength:function(value,length,errorMsg){ if(value.trim().length length){ returnerrorMsg; } }, isMobile:function(value,errorMsg){ if(!/^(13[0-9]|14[5|7]|15[0|1|2|3|5|6|7|8|9]|17[7]|18[0|1|2|3|5|6|7|8|9])\d{8}$/.test(value)){ returnerrorMsg; } } } //验证类 varValidator=function(){ this.cache=[]; } Validator.prototype.add=function(dom,rules){ varself=this; for(vari=0,rule;rule=rules[i++];){ (function(rule){ varstrategyAry=rule.strategy.split(':'); varerrorMsg=rule.errorMsg; self.cache.push(function(){ varstrategy=strategyAry.shift(); strategyAry.unshift(dom.value); strategyAry.push(errorMsg); returnstrategies[strategy].apply(dom,strategyAry); }) })(rule) } }; Validator.prototype.start=function(){ for(vari=0,validatorFunc;validatorFunc=this.cache[i++];){ varerrorMsg=validatorFunc(); if(errorMsg){ returnerrorMsg; } } }; //调用代码 varregisterForm=document.getElementById('registerForm'); varvalidataFunc=function(){ varvalidator=newValidator(); validator.add(registerForm.userName,[{ strategy:'isNoEmpty', errorMsg:'用户名不可为空' },{ strategy:'isNoSpace', errorMsg:'不允许以空白字符命名' },{ strategy:'minLength:2', errorMsg:'用户名长度不能小于2位' }]); validator.add(registerForm.password,[{ strategy:'minLength:6', errorMsg:'密码长度不能小于6位' }]); validator.add(registerForm.phoneNumber,[{ strategy:'isMobile', errorMsg:'请输入正确的手机号码格式' }]); varerrorMsg=validator.start(); returnerrorMsg; } registerForm.onsubmit=function(){ varerrorMsg=validataFunc(); if(errorMsg){ alert(errorMsg); returnfalse; } }
策略模式优缺点
策略模式是一种常用且有效的设计模式。
- 策略模式可以有效避免多重条件选择语句。
- 策略模式提供了对开放-封装原则的完美支持,将方法封装在独立的strategy中,使得它们易于切换,易于理解,易于扩展。
- 复用性高。
当然,策略模式也有一些缺点
- 增加了许多策略类或者策略对象。
- 要使用策略模式,必须了解所有的strategy,违反了最少知识原则。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。