策略模式简介
定义一系列的算法,把它们一个个封装起来,并且使它们可以相互替换
策略模式优点
- 策略模式可以有效地避免多重条件选择语句。
- 支持对修改关闭,对扩展开放原则
- 算法可复用性强
- 在策略模式中利用组合和委托来让 Context 拥有执行算法的能力,这也是继承的一种更轻
便的替代方案。
本文参考书籍:JavaScript设计模式与开发实践
例一:使用策略模式计算奖金
以计算年终奖为例:绩效考核为 S 的人年终奖为工资的4 倍,绩效考核为 A 的人年终奖有 3 倍工资,而绩效考核为 B 的人年终奖是 2 倍工资。假设财 务部要求我们提供一段代码,来方便他们计算员工的年终奖。
1.最初的简单的解决方案:
var Bonus = function( level, salary ){
if ( level === 'S' ){ return salary * 4;
}
if ( level === 'A' ){ return salary * 3;
}
if ( level === 'B' ){ return salary * 2;
} };
Bonus( 'B', 30000 ); // 输出:60000
Bonus( 'S', 80000 ); // 输出:320000
问题如下:
1.若新增其他等级或者修改现有等级的奖金,我们需深入Bonus函数,违反开闭原则。
2.代码复用性差。
2.封装一个个函数重构代码:
var S = function( salary ){
return salary * 4;
};
var A = function( salary ){
return salary * 3;
};
var B = function( salary ){
return salary * 2;
};
var Bonus = function( level, salary ){
if ( level === 'S' ){
return S( salary );
}
if ( level === 'A' ){
return A( salary );
}
if ( level === 'B' ){
return B( salary );
}
};
Bonus( 'S' , 30000 ); // 输出:120000
问题如下:
1.Bonus函数内的if会越来越多。
3.策略模式重构代码:
首先由两部分组成:一个是策略类:它封装了具体的算法及具体的计算过程,第二个是环境类Context,它负责接受传入的请求,接着并把请求委托给一个策略类。!说明:Context中要维持对某个策略对象的引用。
接着我们用策略模式两个版本重构代码:
第一个版本是基于面向对象思想。
var S=function(){
}
S.prototype.calculate=function(salary){
return salary*4
}
var A=function(){
}
A.prototype.calculate=function(salary){
return salary*3
}
var B=function(){
}
B.prototype.calculate=function(salary){
return salary*2
}
var Bonus = function(){
this.salary = null;
this.strategy = null;
};
Bonus.prototype.setSalary = function( salary ){
this.salary = salary; // 设置员工的原始工资
};
Bonus.prototype.setStrategy = function( strategy ){
this.strategy = strategy; // 设置员工绩效等级对应的策略对象
};
Bonus.prototype.getBonus = function(){ // 取得奖金数额
return this.strategy.calculate( this.salary ); // 把计算奖金的操作委托给对应的策略对象
};
var bonus = new Bonus();
bonus.setSalary( 30000 );
bonus.setStrategy( new S() ); // 设置策略对象
console.log( bonus.getBonus() ); // 输出:120000
bonus.setStrategy( new A() ); // 设置策略对象
console.log( bonus.getBonus() ); // 输出:30000
定义一系列的算法,把它们各自封装成策略类,算法被封装在策略类内部的方法里。在对 Context 发起请求的时候,Context 总是把请求委托给这些 策略对象中间的某一个进行计算。
第二个版本:JavaScript 版本的策略模式:把 strategy 直接定义为函数
var stateg={
"S":function(salary){
return salary * 4
},
"A":function(salary){
return salary * 3
}
}
var calculateBouns=function(level,salary){
return stateg[level](salary)
}
console.log(calculateBouns('S',30000));
console.log(calculateBouns('A',20000));
经过改造,代码的结构变得更加简洁
本文参考书籍:JavaScript设计模式与开发实践