策略模式定义了一系列算法分别封装起来,让它们之间可以相互替换,此模式让算法的变化独立于使用算法的的客户。
假如要实现这样一个业务:商城里每个产品都有原价为 originalPrice,但是存在打折促销的情况。规则为:
default 状态,原价出售。100,九折出售;如果原价高于 100,则减20 元。不考虑任何设计模式的写法可能用 if-else 多次判断来计算价格。
- function getPrice(originalPrice, status) {
- if (status === "default") {
- return originalPrice;
- }
- if (status === "pre-sale") {
- return originalPrice * 0.8;
- }
- if (status === "promotion") {
- if (origialPrice <= 100) {
- return origialPrice * 0.9;originalPrice
- } else {
- return originalPrice - 20;
- }
- }
- }
虽然能实现,但存在问题:
第一,它违反了单一职责原则(每个类或者函数都应该有一个单一的功能,并且该功能应该由这个类或者函数完全封装起来)。函数 getPrice 做了太多的事情,如果一个条件出现 bug ,整个函数就会崩溃(一处有问题,所有功能不能实现)
第二,违反了开闭原则(对扩展开放,对修改关闭)。
比如:新增一个活动 “疯狂星期四”crazy-thursday,规则为:
那么,getPrice 函数中需添加以下判断:
- if (status === "crazy-thursday") {
- if (origialPrice >= 100 && originalPrice < 200) {
- return origialPrice - 20;
- } else if (originalPrice >= 200) {
- return originalPrice - 50;
- } else {
- return originalPrice * 0.8;
- }
- }
此时,getPrice函数代码很难应对变化的需求,每次修改已有的功能(每当增加或减少折扣时,都需要更改函数getPrice)很容易出现新的错误,而且还会使得 getPrice 越来越臃肿。
那么,可以同策略模式进行优化:可以使用映射策略 Strategies 而不是冗长的 if-else 来存储对应关系,并拆分这个函数 getPrice 以减少臃肿。
- function defaultPrice(origialPrice) {
- return origialPrice;
- }
-
- function preSalePrice(origialPrice) {
- return originalPrice * 0.8;
- }
-
- function promotionPrice(origialPrice) {
- if (origialPrice <= 100) {
- return origialPrice * 0.9;
- } else {
- return originalPrice - 20;
- }
- }
-
- function crazyhursdayPrice(origialPrice) {
- if (origialPrice >= 100 && originalPrice < 200) {
- return origialPrice - 20;
- } else if (originalPrice >= 200) {
- return originalPrice - 50;
- } else {
- return originalPrice * 0.8;
- }
- }
-
-
- const priceStrategies = {
- "pre-sale": preSalePrice,
- "promotion": promotionPrice,
- "black-friday": blackFridayPrice,
- "default": defaultPrice,
- };
-
- function getPrice(originalPrice, status) {
- return priceStrategies[status](originalPrice);
- }