策略模式
定义:定义一系列的算法,把他们一个个封装起来,并且使他们可以相互替换。
组成:一个策略模式的程序至少由两部分组成。
-
第一部分是一组策略类,策略类封装了具体的算法,并负责具体的计算过程。
-
第二部分是环境类Context,Context接受客户的请求,随后把请求委托给一个策略类。
Context中要维持对摸个策略对象的引用。
JavaScript版本的策略模式
场景1:员工的工资基数和年底绩效发放情况,绩效为S的人年终奖有4倍工资,绩效为A的人年终奖有3倍工资,而绩效为B的人年终奖是2倍工资。
// 策略类
var strategies = {
"S":function(salary){
return salary * 4
}
"A":function(salary){
return salary * 3
}
"B":function(salary){
return salary * 2
}
}
// 环境类
var calculateBonus = function(level,salary){
return strategies[level](salary)
}
console.log(calculateBonus('S',20000)) // 输出:80000
console.log(calculateBonus('A',10000)) // 输出:30000
实际开发中,策略模式可以用来封装"业务规则"。
场景2:表单验证,注册页面,点击注册按钮之前,有如下几条校验逻辑:
-
用户名不能为空
-
密码长度不能少于6位
-
手机号码必须符合格式
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;validatorFuc = this.cache[i++];){
var msg = validatorFun(); // 开始校验,并取得校验后的返回信息
if(msg){
return msg;
}
}
}
// 校验 validator.add(registerForm.userName,'isNonEmpty','用户名不能为空') validator.add(registerForm.userName,'minLength:10','用户名长度不能小于10位')
给一个文本输入框对应多种校验规则??p84
策略模式的优缺点
优点
-
策略模式利用组合、委托和多态等技术和思想,可以有效避免多重条件选择语句
-
对开放-封闭原则的支持,将算法封装在独立的策略对象中,易于切换,易于理解,易于扩展
-
算法可以复用到系统的其他地方,避免许多复制粘贴工作
-
利用组合和委托让Context拥有执行算法的能力,这也是继承的一种更轻便的替代方案
缺点
-
会在程序中增加许多策略类和策略对象
-
使用策略模式必须要了解所有的策略对象,策略对象要向客户暴露它所有的实现,违反了最少知识原则
去掉策略类,如何实现策略模式
var S = function(salary){
return salary * 4
}
var A = function(salary){
return salary * 3
}
var B = function(salary){
return salary * 2
}
var calculateBonus = function(func,salary){
return func(salary)
}
calculateBonus(S,10000) // 输出40000
在JavaScript的策略模式中,策略类往往被函数所替代,这时策略模式就成为一种“隐性”的模式

被折叠的 条评论
为什么被折叠?



