JavaScript设计模式——策略模式

1,249

策略模式:封装一系列算法策略,并使他们之间可以相互替换

在说策略模式之前,我们先简述一下两个基本概念:

  • 环境类(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()

策略模式就是把不变的部分(策略派发)和算法部分抽离开,方便策略新增和替换,增强代码弹性

总结

优点
  • 利用代码组合,有效避免多重条件判断;
  • 代码可服用,易拓展易组合;
缺点
  • 相比直接编写业务逻辑,策略模式会适当增加代码量,主要集中在策略算法;
  • 需要很清晰业务逻辑和策略算法,并准确抽离算法实现过程