一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第29天,点击查看活动详情。
导言
策略模式是行为型设计模式的另一种,在平时的开发中应用很广泛。经常被津津乐道的一种用法是避免大量的if-else判断语句,而用策略模式来替换。
策略模式
定义
策略模式的常用定义是:定义一系列的算法,把它们一个个封装起来,并且使它们可以相互替换。定义一系列的算法,每一种算法也就是一种策略,把它们封装起来,根据不同场景来分别执行具体某种策略。
计算年终奖
我们来举个大家都感兴趣的年终奖的例子,年终奖一般大体都是与员工工资和年终评定绩效等级挂钩,定义ABCD四个等级,不同等级的倍数不同。那我们通过传入员工工资和绩效等级就可以计算出年终奖,如下:
let calcBonus = function (salary, level) {
if (level === 'A') {
return salary * 5
}
if (level === 'B') {
return salary * 4
}
if (level === 'C') {
return salary * 3
}
if (level === 'D') {
return salary * 2
}
}
let xiaomingBonus = calcBonus(20000, 'A')
console.log(xiaomingBonus) // 100000
let lileiBonus = calcBonus(10000, 'C')
console.log(lileiBonus) // 30000
这样,年终奖就计算出来了。代码虽然很简单,但存在明显的问题:
- calcBonus根据绩效等级越来越多,会非常臃肿,同时需要大量的
if-else来覆盖所有分支 - calcBonus函数缺乏弹性,例如每个绩效的系数修改则需要修改内部函数,不符合开闭原则
- 复用性较差
为此,我们用策略模式来改写以上逻辑:
// 每种绩效的计算方式封装到具体策略类中
let PerformanceA = function () {}
PerformanceA.prototype.calc = function (salary) {
return salary * 5
}
let PerformanceB = function () {}
PerformanceB.prototype.calc = function (salary) {
return salary * 4
}
let PerformanceC = function () {}
PerformanceC.prototype.calc = function (salary) {
return salary * 3
}
let PerformanceD = function () {}
PerformanceD.prototype.calc = function (salary) {
return salary * 2
}
// 定义奖金类Bonus
let 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 () {
return this.strategy.calc(this.salary)
}
// 计算年终奖
let bonus = new Bonus()
bonus.setSalary(20000)
bonus.setStrategy(new PerformanceB())
bonus.getBonus()
通过策略模式的修改,首先把各种计算方法单独放在了策略类中,可供覆盖calc方法来重新定义;第二步计算年终奖的方式也封装到了奖金类Bonus类中。第三步我们计算年终奖的时候设置员工工资和对应的策略,年终奖就计算出来了。