策略模式:封装一系列算法策略,并使他们之间可以相互替换
在说策略模式之前,我们先简述一下两个基本概念:
- 环境类(Context):负责接收用户请求,并派发给策略算法执行
- 策略类(Strategy):策略算法具体实现,接收环境类派发的计算请求,并返回计算结果
Question
根据员工绩效等级,实现一个员工奖金计算算法
S => 4 * 月薪
A => 3 * 月薪
B => 2 * 月薪
直观实现
当我们拿到上面的问题,直观想法当然是逻辑判断。如
const calculateBonus = (performanceLevel, salary) => {
if (performanceLevel === 'S') {
return salary * 4
}
if (performanceLevel === 'A') {
return salary * 3
}
if (performanceLevel === 'B') {
return salary * 2
}
return salary
}
calculateBonus('S', 10000)
calculateBonus('A', 5000)
是的,这样写很直观,也很好理解。但是拓展性不强,假如策略变了,新增一个'C'绩效,那就不得不修改计算函数了
策略模式实现
在JavaScript中实现策略模式再简单不过了,可能我们实际开发中已经多次使用,只是没特别留意。如
const Strategy = {
S: (salary) => salary * 4,
A: (salary) => salary * 3,
B: (salary) => salary * 2,
}
const calculateBonus = (performanceLevel, salary) => {
return Strategy[performanceLevel](salary)
}
- calculateBonus:环境类,策略模式中不变的部分;
- Strategy:策略类,算法具体实现过程;
当然,我们也可以采用class实现
class StrategyS {
constructor(salary) {
this.salary = salary
}
calculate() {
return this.salary * 4
}
}
class StrategyA {
constructor(salary) {
this.salary = salary
}
calculate() {
return this.salary * 3
}
}
class StrategyB {
constructor(salary) {
this.salary = salary
}
calculate() {
return this.salary * 2
}
}
class Bonus {
strategy = null
setStrategy(strategy) {
this.strategy = strategy
}
getBonus() {
return this.strategy.calculate()
}
}
const bonus = new Bonus()
bonus.setStrategy(new StrategyS(10000))
bonus.getBonus()
策略模式就是把不变的部分(策略派发)和算法部分抽离开,方便策略新增和替换,增强代码弹性
总结
优点
- 利用代码组合,有效避免多重条件判断;
- 代码可服用,易拓展易组合;
缺点
- 相比直接编写业务逻辑,策略模式会适当增加代码量,主要集中在策略算法;
- 需要很清晰业务逻辑和策略算法,并准确抽离算法实现过程