策略模式(js)

定义

        策略模式定义了一系列算法分别封装起来,让它们之间可以相互替换,此模式让算法的变化独立于使用算法的的客户。

优点

  • 利用组合、委托等技术,可以有效的避免多重条件选择语句
  • 提供了对开放-封闭原则的完美支持,将算法封装在独立的strategy中,使得它们易于切换扩展
  • 利用组合和委托来让Context拥有执行算法的能力,这也是继承的一种更轻便的代替方案

使用

        假如要实现这样一个业务:商城里每个产品都有原价为 originalPrice,但是存在打折促销的情况。规则为:

  • 部分产品不参与活动: default 状态,原价出售。
  • 部分产品已预售:pre-sale 状态,原价基础上打八折。
  • 部分产品参与促销活动:promotion 状态,如果原价不高于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,规则为:

  • 价格低于或等于 100 元的产品以 20% 的折扣出售。
  • 价格高于 100 元但低于 200 元的产品将减少 20 元。
  • 价格高于或等于 200 元的产品将减少 20 元。

那么,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);
}

缺点

  • 会在程序中增加许多策略类或者策略对象
  • 要使用策略模式,必须了解所有的strategy,必须了解各个strategy之间的不同点,这样才能选择一个合适的strategy


 

        

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小白目

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值