合规国际互联网加速 OSASE为企业客户提供高速稳定SD-WAN国际加速解决方案。 广告
## :-: 设计模式的“前端化” -- 策略模式 ### 什么是设计模式: 设计模式 = 解决方案 解决软件设计中普遍存在(反复出现)的各种问题, 不必做重复劳动 ### 设计模式的核心思想——封装变化 但在实际开发中,不发生变化的代码可以说是不存在的 我们能做的只有将这个变化造成的影响最小化 将变与不变分离,确保变化的部分灵活、不变的部分稳定。 ## 一: 策略模式:重构小能手-拆分胖逻辑 举个 🌰 : 有一天,产品经理韩梅梅找到李雷,给李雷提了这么个需求: 马上大促要来了,我们本次大促要做**差异化询价**。啥是差异化询价?就是说同一个商品,我通过在后台给它设置不同的价格类型,可以让它展示不同的价格。具体的逻辑如下: * 当价格类型为“预售价”时,满 100 - 20,不满 100 打 9 折 * 当价格类型为“大促价”时,满 100 - 30,不满 100 打 8 折 * 当价格类型为“返场价”时,满 200 - 50,不叠加 * 当价格类型为“尝鲜价”时,直接打 5 折 李雷扫了一眼 prd,立刻来了主意。他首先将四种价格做了标签化: 预售价 - pre 大促价 - onSale 返场价 - back 尝鲜价 - fresh 接下来李雷仔细研读了 prd 的内容,作为资深 if-else 侠,他三下五除二就写出一套功能完备的代码: ``` // 询价方法,接受价格标签和原价为入参 function askPrice(tag, originPrice) { // 处理预热价 if(tag === 'pre') { if(originPrice >= 100) { return originPrice - 20 } return originPrice \* 0.9 } // 处理大促价 if(tag === 'onSale') { if(originPrice >= 100) { return originPrice - 30 } return originPrice \* 0.8 } // 处理返场价 if(tag === 'back') { if(originPrice >= 200) { return originPrice - 50 } return originPrice } // 处理尝鲜价 if(tag === 'fresh') { return originPrice \* 0.5 } } ``` 这么写代码会带来什么后果: * 违背了“单一功能”原则 (比如说万一其中一行代码出了 Bug,那么整个询价逻辑都会崩坏) * 违背了“开放封闭”原则 (只要加需求 就需要继续 if - else,对测试同学不太友好) ## 重构询价逻辑 1. 单一功能改造 prePrice - 处理预热价 onSalePrice - 处理大促价 backPrice - 处理返场价 freshPrice - 处理尝鲜价 askPrice - 分发询价逻辑 ``` // 处理预热价 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) { ... } // 处理尝鲜价 function freshPrice(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) } } ``` 问题: askPrice 的函数体,还是没有实现“对扩展开放,对修改封闭”,新需求来了,还要继续 if 2. 开放封闭改造 其实 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) { ... }, fresh(originPrice) { ... }; } ``` ``` // 询价函数 function askPrice(tag, originPrice) { return priceProcessor[tag](originPrice) } ``` 如此一来,askPrice 函数里的 if-else 大军彻底被消灭了。这时候如果需要一个新人价,只需要给 priceProcessor 新增一个映射关系。这样完成对扩展开放,对修改封闭了。 这,就是策略模式!