策略模式
策略模式指的是定义一些列的算法,把他们一个个封装起来,目的就是将算法的使用与算法的实现分离开来。说白了就是以前要很多判断的写法,现在把判断里面的内容抽离开来,变成一个个小的个体。
表单校验为例:
<form action="http:// xxx.com/register" id="registerForm" method="post"> 请输入用户名:<input type="text" name="userName" /> 请输入密码:<input type="text" name="password"/> 请输入手机号:<input type="text" name="phoneNumber" /> <button>提交</button> </form>
常见的代码编写方式:
var registerForm = document.getElementById('registerForm'); registerForm.onsubmit = function(){ if (registerForm.userName.value == '') { alert('用户名不能为空'); return false; } if (registerForm.password.value.length < 6) { alert('密码长度不能少于6位'); return false; } if (!/(^1[3|5|8][0-9]{9}$)/.test(registerForm.phoneNumber.value)) { alert('手机号格式不正确'); return false; } }
策略模式:
这个模式涉及到三个角色:
- 具体策略(ConcreteStrategy)角色:包装了相关的算法或行为。
- 抽象策略(Strategy)角色:这是一个抽象角色,通常由一个接口或抽象类实现。此角色给出所有的具体策略类所需的接口。
- 环境(Context)角色:持有一个Strategy的引用。
第一步封装策略对象(算法):
var strategies = { isNonEmpty:function(value,errorMsg){ //不为空 if (value === '') { return errorMsg; } }, minLength:function(value,length,errorMsg){ //限制最小长度 if (value.length < length) { return errorMsg; } }, isMobile:function(value,errorMsg){ //手机号格式 if (!/(^1[3|5|8][0-9]{9}$).test(value)) { return errorMsg; } } }
第二步封装抽象类(接口):
var Validator = function(){ this.cache = []; //保存校验规则 } Validator.prototype.add = function(dom,rule,errorMsg){ var ary = rule.split(':'); //把strategy和参数分开 this.cache.push(function(){ //把校验的步骤都用空函数包装起来,并且放入cache var strategy = ary.shift(); //用户挑选的strategy ary.unshift(dom.value); //把input的value添加进参数列表 ary.push(errorMsg); //把errorMsg添加进参数列表 return strategies[strategy].apply(dom,ary); }) } Validator.prototype.start = function(){ for (var i = 0,validatorFunc;validatorFunc = this.cache[i++];) { var msg = validatorFunc(); //开始校验,并取得校验后的返回信息 if(msg){ //如果有确切的返回值,说明校验没有通过 return msg; } } }
第三步策略的实现(引用):
var validataFunc = function(){ var validator = new Validator(); //创建一个validator类 /*******************添加一些校验规则*********************/ validator.add(registerForm.userName,'isNonEmpty','用户名不能为空'); validator.add(registerForm.password,'minLength:6','密码长度不能少于6位'); validator.add(registerForm.phoneNumber,'isMobile','手机号码格式不正确'); var errorMsg = validator.start(); //获得校验结果 return errorMsg; //返回校验结果 } var registerForm = document.getElementById('registerForm'); registerForm.onsubmit = function(){ var errorMsg = validataFunc(); //如果errorMsg有确切的返回值,说明未通过校验 if(errorMsg){ alert(errorMsg); return false; //阻止表单提交 } }