策略模式的定义:定义一系列的算法,把它们一个个封装起来,并且使他们可以相互替换。
我们编写一个函数来计算每个人的奖金数额,这个函数接收两个参数:员工的工资数额和他的绩效考核等级
const calulateBous = (performanceLevel, salary) => {
switch(performanceLevel) {
case 'S':
return salary*4
case 'A':
return salary*3
case 'B':
return salary*2
}
}
我们可以看到上面那段代码有几个缺点:
case
语句,这些语句需要覆盖所有的逻辑分支 calulateBous
函数缺乏弹性,如果需要增加一个新的绩效等级 C,那我们必须深入 calulateBous
函数内部去实现,这是违反 开放-封闭原则
的 因此,我们需要重构这段代码
const performanceS = (salary) => {
return salary*4
}
const performanceA = (salary) => {
return salary*3
}
const performanceB = (salary) => {
return salary*2
}
const calulateBous = (performanceLevel, salary) => {
switch(performanceLevel) {
case 'S':
return performanceS(salary)
case 'A':
return performanceA(salary)
case 'B':
return performanceB(salary)
}
}
目前,我们的程序得到了一点的改善,但是这种改善非常有限,我们依然没有解决最重要的问题: calulateBous
函数有可能越来越庞大,并且在系统变化时缺乏弹性。
const performanceS = function(){}
performanceS.prototype.calulate = salary => {
return salary*4
}
const performanceA = function(){}
performanceA.prototype.calulate = salary => {
return salary*3
}
const performanceB = function(){}
performanceB.prototype.calulate = salary => {
return salary*3
}
const Bonus = function(){
this.salary = null // 原始工资
this.strategy = null // 绩效等级对应的策略对象
}
Bonus.prototype.setSalary = salary => {
this.salary = salary
}
Bonus.prototype.setStrategy = strategy => {
this.strategy = strategy
}
Bonus.prototype.getBonus = () => {
return this.strategy.calulate(this.salary)
}
在 JavaScript 中,函数也是对象,所以更简单和直接的方法就是将 strategy 直接定义为对象。
const strategies = {
S(salary) {
return salary*4
},
A(salary) {
return salary*3
}
B(salary) {
return salary*2
}
}
同样的,Context 也没必要用 Bonus 来表示,我们依旧用 calculateBonus 来充当 Context 来接收用户的请求。
const calulateBous = (performanceLevel, salary) => {
return strategies[performanceLevel](salary)
}