定义
策略模式定义了一系列算法,并将每个算法封装起来,使它们可以相互替换,且算法的变化不会影响使用算法的客户。策略模式属于对象行为模式,它通过对算法进行封装,把使用算法的责任和算法的实现分割开来,并委派给不同的对象对这些算法进行管理。
简而言之,就是策略模式准备了一组算法,并将每个算法进行封装,使它们之间可用相互替换。 策略模式除了用来封装算法,也可以用来封装一系列的"业务规则",只要这些业务规则指向的目标一致,并且可以被替换使用,我们就可以用策略模式来封装它们。
例子:购物车结算时有多种折扣计算方式,满100-10,满200-25,8折,7折,这种逻辑我们可以用基本代码实现
function calcPrice(price, type) {
if (type === '100-10') {
price -= 10
} else if (type === '200-25') {
price -= 25
} else if (type === '80%') {
price *= 0.8
}
return price
}
const res = calcPrice(320, '100-10')
显而易见,这段代码虽然实现了我们想要的功能,但是很局限,有以下几种缺点:
- 一旦折扣种类修改,需要反复改源代码,违反了开放封闭原则
- 很容易陷入多重条件地狱,不断去累加判断条件
- 算法无复用性,在程序的其他地方需要重用,只能复制粘贴
相关概念
一个基于策略模式的程序至少由两部分组成。第一个部分是一组策略类,第二个部分是环境类Context。- 策略类:策略类封装了具体的算法,并负责具体的计算过程。
- 环境类Context:环境类Context接受客户的请求,随后把请求委托给某一个策略类。
const calcPrice = (function () {
const sale = {
'100-10': function (price) { return price -= 10 },
'200-25': function (price) { return price -= 25 },
'80%': function (price) { return price *= 0.8 }
}
return function(price,type) {
// 判断对象里有没有这个折扣类型
if (!sale[type]) return '没有这个折扣'
return sale[type](price)
}
})()
console.log(calcPrice(320,'100-10'))
// 替换 Context 中当前保存的策略对象,便能执行不同的算法来得到我们想要的结果。
// 增加添加和删除折扣的接口
const calcPrice = (function () {
const sale = {
'100-10': function (price) {return price -= 10},
'200-25': function (price) {return price -= 25},
'80%': function (price) {return price *= 0.8}
}
function calcPrice(price, type) {
if (!sale[type]) return '没有这个折扣'
return saletype
}
calcPrice.add = function (type, fn) {
// 判断折扣是否存在
if (sale[type])
sale[type] = fn
return '添加成功'
}
// 删除折扣
calcPrice.del = function (type) {
delete sale[type]
}
return calcPrice
})()
// 添加折扣
calcPrice.add('70%', function (price) {return price *= 0.7})
// console.log(calcPrice(300,'70%'))
// 删除折扣
calcPrice.del('100-10')
// console.log(calcPrice(300,'100-10'))
策略模式的优缺点
从上述的例子中,很明显能总结出策略模式的优点
- 采用组合、委托和多态等技术和思想、有效避免了多重条件选择语句
- 采用了开放-封闭原则,将算法封装在独立的strategy中,易于理解、切换、拓展
- 策略模式中的算法可以进行复用,从而避免很多地方的复制粘贴
同时策略模式也有其缺点,但是并不影响我们对策略模式的使用
- 在策略模式中,我们会增加很多策略类、策略对象
- 要使用策略模式,我们必须了解到所有的strategy、必须了解各个strategy之间的不同点,才能选择一个适合的strategy。