策略模式:一个问题匹配多个解决方案,不一定要用到哪一个;有可能会增加或删除多个方案。
例如:假设需要定义一个奖金计算函数,不同级别对应不同的倍数。
一、普通模式
// 1. 定义奖金计算函数
const calculateBonusNormal = function (level, salary) {
if (level === 'S') {
return salary * 4
}
else if (level === 'A') {
return salary * 3
}
else if (level === 'B') {
return salary * 2
} else {
return salary
}
}
// 2. 测试
console.log(calculateBonusNormal('S', 20000))
console.log(calculateBonusNormal('A', 10000))
console.log(calculateBonusNormal('B', 5000))
console.log(calculateBonusNormal('C', 5000))
二、策略模式
// 1. 定义策略
const strategies = {
'S': function (salary) {
return salary * 4
},
'A': function (salary) {
return salary * 3
},
'B': function (salary) {
return salary * 2
}
}
// 2. 定义奖金计算函数
const calculateBonus = function (level, salary) {
return strategies[level] ? strategies[level](salary) : salary
}
// 3. 测试
console.log(calculateBonus2('S', 20000)) //80000
console.log(calculateBonus2('A', 10000)) //30000
console.log(calculateBonus2('C', 10000)) //10000
三、增加或删除策略
// 4.增加策略等级
strategies['E'] = function (salary) {
return salary * 5
}
// 5.优化-增加策略等级写成统一方法
strategies.add = function (level, fn) {
strategies[level] = fn
}
// 6.使用5的方法增加策略等级
strategies.add('D', function (salary) {
return salary * 0.5
})
// 7.测试
console.log(calculateBonus3('S', 20000))
console.log(calculateBonus3('A', 10000))
console.log(calculateBonus3('C', 10000))
console.log(calculateBonus3('D', 10000))
// 8.删除策略等级
delete strategies['D']
// 9.优化-删除策略等级写成统一方法
strategies.del = function (level) {
delete strategies[level]
}
// 10.使用9的方法删除策略等级
strategies.del('C')
// 11.测试
console.log(calculateBonus3('S', 20000))
console.log(calculateBonus3('A', 10000))
console.log(calculateBonus3('C', 10000))
console.log(calculateBonus3('D', 10000))
策略模式的优点之一在于:策略模式使代码更加灵活和可维护。通过将算法和它们的实现分离,可以更轻松地添加、删除或更改算法。
例如:如果想批量添加或者删除策略等级,使用策略模式的情况下我们可以很容易实现:
//定义一个数组保存要加入的策略等级和相关数据
let arr = [{level:'F',times:6},{level:'H',times:7},{level:'J',times:8}]
arr.forEach(item=>{
strategies.add(item.level,function(salary){
return salary*item.times
})
})
// 19. 测试
console.log(calculateBonus3('F', 20000))
console.log(calculateBonus3('H', 10000))
console.log(calculateBonus3('J', 10000))
总结
策略模式实现方式即:把多种方案以闭包的形式保存起来,对外留一个接口,可以添加和删除。