一、定义
定义一系列的算法,把它们一个个封装起来,并且使它们可以相互替换。
二、核心
将算法的使用和算法的实现分离开来。
一个基于策略模式的程序至少由两部分组成:
第一个部分是一组策略类,策略类封装了具体的算法,并负责具体的计算过程。
第二个部分是环境类Context,Context接受客户的请求,随后把请求委托给某一个策略类。要做到这点,说明Context 中要维持对某个策略对象的引用。
三、实现
策略模式可以用于组合一系列算法,也可用于组合一系列业务规则。
// 例如要写一个计算两个数加减乘除的方法
function countNum (type, num1, num2) {
if (type === 'add') {
return num1 + num2
} else if (type === 'subtract') {
return num1 - num2
} else if (type === 'multiply') {
return num1 * num2
} else {
return num1 / num2
}
}
console.log(countNum('add', 9, 3)) // 12
console.log(countNum('subtract', 9, 3)) // 6
console.log(countNum('multiply', 9, 3)) // 27
console.log(countNum('', 9, 3)) // 3
作如下优化:
let calculateNum = {
add(num1, num2) {
return num1 + num2
},
subtract(num1, num2) {
return num1 - num2
}, multiply(num1, num2) {
return num1 * num2 },
divide(num1, num2) {
return num1 / num2
},
}
console.log(calculateNum.add(6, 2)) // 8
console.log(calculateNum.subtract(6, 2)) // 4
console.log(calculateNum.multiply(6, 2)) // 12
console.log(calculateNum.divide(6, 2)) // 3
该例子就可以看成是一个策略模式。
#又例如,商场搞促销,有部分商品打8折、部分商品打9折、满100减20、会员满100减30等活动,可以用策略模式来实现:
// 定义一个策略对象
let priceceStrategy = function() {
// 内部算法对象
let strategy = {
return20(price){
return price - parseInt(price / 100) * 20
},
return30(price){
return price - parseInt(price / 100) * 30
},
price80(price){
return price * 80 / 100
},
price90(price){
return price * 90 / 100
}
}
// 策略方法调用接口
return {
strategyFunction(type, price) {
return strategy[type] && strategy[type](price)
},
// 添加算法
addStrategy(type, fn){
strategy[type] = fn
}
}
}()
console.log(priceceStrategy.strategyFunction('return20', 200)) // 160
console.log(priceceStrategy.strategyFunction('return30', 300)) // 210
console.log(priceceStrategy.strategyFunction('price80', 100)) // 80
console.log(priceceStrategy.strategyFunction('price90', 100)) // 90
// 添加一个算法: 满100减50
priceceStrategy.addStrategy('return50', (price) => {
return price - parseInt(price / 100) * 50
})
console.log(priceceStrategy.strategyFunction('return50', 100)) // 50
优缺点
优点:
- 优化多重条件判断,采用策略模式是的算法更利于维护;
- 可扩展性,策略模式提供了对“开闭原则”的完美支持,用户可以在不修改原有系统的基础上选择算法或行为,也可以灵活地增加新的算法或行为;
- 策略类之间可以自由切换,由于策略类都实现同一个接口,所以使它们之间可以自由切换。
缺点:
- 由于选择哪种算法的决定权在用户,所以对用户来说就必须了解每种算法的实现;
- 由于每种算法间相互独立,这样对于一些复杂的算法处理相同逻辑的部分无法实现共享,这就会造成一些资源的浪费。