策略模式
策略模式指的是定义一些列的算法,把他们一个个封装起来,目的就是将算法的使用与算法的实现分离开来。说白了就是以前要很多判断的写法,现在把判断里面的内容抽离开来,变成一个个小的个体。
表单校验为例:
<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; //阻止表单提交
}
}