策略模式与开发实践

时间:2021-09-04 21:58:55

前言

昨天学习了单例模式在前端中的应用实践,今天来看看策略模式的应用实践。


策略模式

策略模式的定义是:定义一系列的算法,把它们一个个封装起来,并且使它们可以相互替换。

在应用中,策略模式可以用来优化具有很多不同判读分支的场景。

我们先来看一个例子,根据不同的绩效成绩来算年终奖。(说到奖金我就开心,哈哈)


简单的多条件判断

我们根据不同的绩效来发奖金:

var calculateBonus = function(rank,salary){
if(rank === 'S'){
return salary*4;
}
if(rank === 'A'){
return salary*3;
}
if(rank === 'B'){
return salary*2;
}
}
calculateBonus('S',20000);//80000

这样的代码有一个问题,就是当情况越来越多,就得修改calculateBonus函数内部,这就违反了开放-封闭原则。


使用策略模式重构

前面说到过,策略模式是定义一系列的算法,把它们一个个封装起来。其目的就是将算法的使用与算法的实现分离开来。

在上面的例子中,算法的使用的不变的,就是根据某个算法得到计算后的奖金,而算法的实现是根据条件变化的。

//算法的实现
var strategies = {
'S':function(salary){
return salary*4;
},
'A':function(salary){
return salary*3;
},
'B':function(salary){
return salary*2;
}
};
//算法的使用
var calculateBonus = function(rank,salary){
return strategies[rank](salary);
}

一个简单的策略模式就完成了。


使用策略模式验证表单

前面只是一个小例子,目的是介绍策略模式这样思想。现在以工程应用中的表单验证为例,说说策略模式的作用。

普通的验证

最常见的验证方式:

form.onsubmit = function(){
//一个一个的验证,非常繁琐
if(form.name.value === ''){
alert('用户名不能为空')
return false;
}
if(form.password.value.length <6){
alert('长度不能少于6');
return false;
}
}

如此为每一个条件都进行一次判断,势必会带来很多的复制粘贴。

策略模式的验证

下来看看我们如何通过使用策略模式来重构表单验证:

//定义验证策略
var strategies = {
inNonEmpty:function(value,errorMsg){//不能为空
if(value === ''){
return errorMsg;
}
},
minLength:function(value,length,errorMsg){//最小长度
if(value.length < length){
return errorMsg;
}
},
isReg:function(value,reg,errorMsg){//正则匹配
if(!reg.test(value)){
return errorMsg;
}
}
};
//定义验证类
var Validator = function(){
this.cache = [];//保存效验规则
};
//添加验证规则
Validator.prototype.add = function(dom,rules){
var that = this;
//多条规则分别对应
for(var i = 0 ,rule; rule = rules[i++];){
(function(rule){
var stratgyAry = rule.strategy.split(':');
var errorMsg = rule.errorMsg;
//将数据按照策略的格式塞入参数数组
that.cache.push(function(){
var strategy = strategyAry.shift();
strategyAry.unshift(dom.value);
strategyAry.push(errorMsg);
return strategies[strategy].apply(dom,strategyAry);
});
})(rule)
}
};
Validator.prototype.start = function(){
//依次验证
for(var i = 0,validatorFunc;validatorFunc = this.cache[i++];){
var errorMsg = validatorFunc();
if(errorMsg){
return errorMsg;
}
}
};

//调用代码
var validataFunc = function(){
var validator = new Validator();
//多个条件判断
validator.add(form.name,[{
strategy:'isNonEmpty',
errorMsg:'用户不能为空'
},{
strategy:'minLength:10',
errorMsg:'用户长度不能小于10位'
}]);
validator.add(form.password,[{
strategy:'minLength:6',
errorMsg:'密码长度不能低于6位'
}]);
var errorMsg = validator.start();
return errorMsg;
}
form.onsubmit = function(){
var errorMsg = validateFunc();
if(errorMsg){
alert(errorMsg);
return false;
}
//验证通过,提交表单
}

这样的解决方案可能看起来代码量会多一些,而且比较复杂,但是维护和拓展起来就比较方便了,而且复用性也会比较强。这也就达到了策略模式的作用。


感悟

总体来说,策略模式可以有效避免多重条件选择语句,从而避免许多重复的复制粘贴工作。