定义:定义一系列的算法,把他们一个个封装起来,并且使他们可以相互替换。
详细解释:定义一系列的算法,把它们各自封装成策略类,算法被封装在策略类内部的方法里。
应用场景:
缓动动画
验证表单
优点:
策略模式利用组合、委托和多态等技术和思想,可以有效地避免多重条件选择语句。
策略模式提供了对开放-封闭原则的完美支持,将算法封装在独立的strategy中,使得它们易于切换,易于理解,易于拓展。
策略模式中的算法也可以复用在系统的其他地方,从而避免许多的复制粘贴工作。
在策略模式中利用组合和委托来让Context拥有执行算法的能力,这也是继承的一种更轻便的替代方案。
缺点:
使用策略模式会在程序中增加许多策略类或者策略对象,但实际上这比吧它们负责的逻辑堆砌在Context中要好。
要使用策略模式,必须了解所有的strategy,必须了解各个strategy之间的不同点,这样才能选择一个合适的strategy。比如,我们要选择一种合适的旅游路线,必须先了解选择飞机、火车、自行车等方案的细节。此时strategy要向客户暴露它的所有实现,这是违反最少知识原则的。
// 计算奖金 - 绩效为S的人年终奖有4倍工资,绩效为A的人年终奖有3倍工资,而绩效为B的人年终奖是2
// 倍工资。提供一段代码来计算员工的年终奖。
// 最初的代码实现
var calculateBonus = function(performanceLevel, salary){
if(performanceLevel === 'S'){
return salary * 4
}
if(performanceLevel === 'A'){
return salary * 3
}
if(performanceLevel === 'B'){
return salary * 2
}
}
calculateBonus('B', 20000) // 40000
calculateBonus('S', 6000) // 24000
// 使用组合函数重构代码 - 我们把各种算法封装到一个个小函数里面,这些小函数有着良好的命名,可
// 以一目了然地知道它对应着哪种算法。他们也可以被复用在程序的其他地方。
var performanceS = function(salary){
return salary * 4
}
var performanceA = function(salary){
return salary * 3
}
var performanceB = function(salary){
return salary * 2
}
var calculateBonus = function(performanceLevel, salary){
if(performanceLevel === 'S'){
return performanceS(salary)
}
if(performanceLevel === 'A'){
return performanceA(salary)
}
if(performanceLevel === 'B'){
return performanceB(salary)
}
}
calculateBonus('A', 10000) // 30000
// 使用策略模式重构代码 - 一个基于策略模式的程序至少由两部分组成。第一部分是一组策略类,策
// 略类封装了具体的算法,并负责具体的计算过程。第二个部分是环境类Context,Context接受客户
// 的请求,随后把请求委托给某一个策略类。
// (模仿传统面向对象语言中的实现)
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 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(){
if(!this.strategy){
throw new Error('未设置strategy')
}
return this.strategy.calculate(this.salary) //委托给对应的策略类
}
var bonus = new Bonus()
bonus.setSalary(10000)
bonus.setStrategy(new performanceS)
console.log(bonus.getBonus()) // 40000
bonus.setStrategy(new performanceA)
console.log(bonus.getBonus()) // 30000
// JavaScript版本的策略模式
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