策略模式
定义一系列算法,把它们一个个封装起来,并且使它们可以相互替换
策略模式一般分为策略类(封装具体算法,负责策略的具体逻辑计算) + 环境类(接收用户请求,把请求委托给某一策略),将算法的使用和算法的实现分离开来,消除大量条件分支语句。
在具体应用中,我们常常会遇到根据状态,选择不同的处理逻辑。通常会用if-else来处理,或者switch。但是大量业务逻辑和状态判断封装在一起,函数显得冗余又杂乱。
那应该怎么做?
以超市打折的场景为例:
当价格类型为“预售价”时,满 100 - 20,不满 100 打 9 折
当价格类型为“大促价”时,满 100 - 30,不满 100 打 8 折
当价格类型为“返场价”时,满 200 - 50,不叠加
当价格类型为“尝鲜价”时,直接打 5 折
- 首先,对每种状态的逻辑处理封装成函数(对应策略类)。然后判断类型,选择处理函数(对应环境类)。
// 处理预热价
function prePrice(originPrice) {
if(originPrice >= 100) {
return originPrice - 20
}
return originPrice * 0.9
}
// 处理大促价
function onSalePrice(originPrice) {
if(originPrice >= 100) {
return originPrice - 30
}
return originPrice * 0.8
}
// 处理返场价
function backPrice(originPrice) {
if(originPrice >= 200) {
return originPrice - 50
}
return originPrice
}
// 处理尝鲜价
function freshPrice(originPrice) {
return originPrice * 0.5
}
// 处理新人价
function newUserPrice(originPrice) {
if(originPrice >= 100) {
return originPrice - 50
}
return originPrice
}
function askPrice(tag, originPrice) {
// 处理预热价
if(tag === 'pre') {
return prePrice(originPrice)
}
// 处理大促价
if(tag === 'onSale') {
return onSalePrice(originPrice)
}
// 处理返场价
if(tag === 'back') {
return backPrice(originPrice)
}
// 处理尝鲜价
if(tag === 'fresh') {
return freshPrice(originPrice)
}
// 处理新人价
if(tag === 'newUser') {
return newUserPrice(originPrice)
}
}
但是,代码看起来好像还是很冗余,并且没有实现“对扩展开放,对修改封闭”的效果。其中在判断类型时还是采用多个if-else语句来实现与处理函数的映射关系,那么在 JS 中,有没有什么既能够既帮我们明确映射关系,同时不破坏代码的灵活性的方法呢?答案就是对象映射!
- 把逻辑处理函数封装在一个对象
// 定义一个询价处理器对象
const priceProcessor = {
pre: originPrice => {
if (originPrice >= 100) {
return originPrice - 20;
}
return originPrice * 0.9;
},
onSale:originPrice => {
if (originPrice >= 100) {
return originPrice - 30;
}
return originPrice * 0.8;
},
back: originPrice => {
if (originPrice >= 200) {
return originPrice - 50;
}
return originPrice;
},
fresh: originPrice => {
return originPrice * 0.5;
},
};
- 当需要某个类型对应处理函数时,可直接调用对象方法
function askPrice(tag, originPrice) {
return priceProcessor[tag](originPrice)
}
- 如果想新增策略,只需要给对象添加一个方法
priceProcessor.newUser = function (originPrice) {
if (originPrice >= 100) {
return originPrice - 50;
}
return originPrice;
}
总结:在日常使用中,如果有大量状态判断以及逻辑处理,可以采用策略模式,将状态判断以及逻辑处理拆分,消除大量条件分支语句,同时实现“对扩展开放,对修改封闭”的原则。不要做if-else侠啦!
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。