将不变的部分和变化的部分隔开是每个设计的主题
策略模式的定义:定义一系列的算法,把它们一个个封装起来,并且使它们可以相互替换。策略模式至少由两个部分组成。第一部分是一组策略类,策略类封装了具体的算法,并负责具体的计算过程。第二个部分是环境类context,context接受客户的请求,随后把请求委托给某一个策略类。
使用场景:根据员工绩效和工资基数发放年终奖,例如:绩效s的人年终有四倍工资,绩效a的人三倍,绩效b的人两倍
策略类:
var performanceS = function(){
performanceS.prototype.calculate = function(salary){
return salary*4
}
}
var performanceA = function(){
performanceA.prototype.calculate = function(salary){
return salary*3
}
}
var performanceB = function(){
performanceB.prototype.calculate = function(salary){
return salary*2
}
}
环境类
var Bouns = function(){
this.salary = null; //原始工资
this.strategy = null; //绩效等级对应的策略对象
}
Bouns.prototype.setSalary = function(salary){
this.salary = salary //设置员工的原始工资
}
Bouns.prototype.setStrategy = function(strategy){
this.strategy = strategy //设置员工绩效等级对应的策略对象
}
Bouns.prototype.getBouns=function(){
if(!this.strategy){
throw new Error('未设置startegy属性')
}
return this.strategy.calculate(this.salary)
//把计算奖金的操作委托给对应的策略对象
}
使用
var bonus = new Bouns();
bonus.setSalary(1000);
bonus.setStrategy(new performanceS()); //设置策略对象
console.log(bonus.getBouns()) //输出:4000
bonus.setStrategy(new performanceA()); //设置策略对象
console.log(bonus.getBouns()) //输出:3000
javascript改造以后
var strategies = {
'S':function(salary){
return salary*4
},
'A':function(salary){
return salary*3
},
'B':function(salary){
return salary*2
}
}
var calculateBouns = function(level,salary){
return strategies[level](salary)
}
console.log(calculateBouns('S',2000))//输出:8000
console.log(calculateBouns('A',1000))//输出:3000
策略模式优缺点:
1.策略模式利用组合、委托、和多态等技术和思想,可以有效的避免多重条件选择语句。
2.策略模式提供了对外开放-封闭原则的完美支持,将算法封装在独立的strategy中,使它们易于切换,理解和扩张。
3.策略模式的算法也可以复用在系统的其他地方,从而避免许多重复的复制黏贴工作。
4.策略模式中利用组合和委托让context拥有执行算法的能力,这也是继承的一种更轻便的替代方案。
缺点:策略模式会在程序中增加很多策略类或者策略对象。但是比把逻辑放在context中要好。
注意:使用策略模式,必须了解所有的ctrategy(策略)必须了解各个strategy之间的不同点,这样才能选择一个合适的strategy。比如要选择合适的旅游路线,必须先了解选择飞机,火车,自行车等方案的细节。此时strategy要向客户暴露他的所有实现,这是违反最少知识原则的。