• 策略模式(js)


    定义

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

    优点

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

    使用

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

    • 部分产品不参与活动: default 状态,原价出售。
    • 部分产品已预售:pre-sale 状态,原价基础上打八折。
    • 部分产品参与促销活动:promotion 状态,如果原价不高于100,九折出售;如果原价高于 100,则减20 元。

    不考虑任何设计模式的写法可能用 if-else 多次判断来计算价格。

    1. function getPrice(originalPrice, status) {
    2. if (status === "default") {
    3. return originalPrice;
    4. }
    5. if (status === "pre-sale") {
    6. return originalPrice * 0.8;
    7. }
    8. if (status === "promotion") {
    9. if (origialPrice <= 100) {
    10. return origialPrice * 0.9;originalPrice
    11. } else {
    12. return originalPrice - 20;
    13. }
    14. }
    15. }

    虽然能实现,但存在问题:

            第一,它违反了单一职责原则(每个类或者函数都应该有一个单一的功能,并且该功能应该由这个类或者函数完全封装起来)。函数 getPrice 做了太多的事情,如果一个条件出现 bug ,整个函数就会崩溃(一处有问题,所有功能不能实现)

            第二,违反了开闭原则(对扩展开放,对修改关闭)。

    比如:新增一个活动 “疯狂星期四”crazy-thursday,规则为:

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

    那么,getPrice 函数中需添加以下判断:

    1. if (status === "crazy-thursday") {
    2. if (origialPrice >= 100 && originalPrice < 200) {
    3. return origialPrice - 20;
    4. } else if (originalPrice >= 200) {
    5. return originalPrice - 50;
    6. } else {
    7. return originalPrice * 0.8;
    8. }
    9. }

     此时,getPrice函数代码很难应对变化的需求,每次修改已有的功能(每当增加或减少折扣时,都需要更改函数getPrice)很容易出现新的错误,而且还会使得 getPrice 越来越臃肿。

    那么,可以同策略模式进行优化:可以使用映射策略 Strategies 而不是冗长的 if-else 来存储对应关系,并拆分这个函数 getPrice 以减少臃肿。

    1. function defaultPrice(origialPrice) {
    2. return origialPrice;
    3. }
    4. function preSalePrice(origialPrice) {
    5. return originalPrice * 0.8;
    6. }
    7. function promotionPrice(origialPrice) {
    8. if (origialPrice <= 100) {
    9. return origialPrice * 0.9;
    10. } else {
    11. return originalPrice - 20;
    12. }
    13. }
    14. function crazyhursdayPrice(origialPrice) {
    15. if (origialPrice >= 100 && originalPrice < 200) {
    16. return origialPrice - 20;
    17. } else if (originalPrice >= 200) {
    18. return originalPrice - 50;
    19. } else {
    20. return originalPrice * 0.8;
    21. }
    22. }
    23. const priceStrategies = {
    24. "pre-sale": preSalePrice,
    25. "promotion": promotionPrice,
    26. "black-friday": blackFridayPrice,
    27. "default": defaultPrice,
    28. };
    29. function getPrice(originalPrice, status) {
    30. return priceStrategies[status](originalPrice);
    31. }

    缺点

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


     

            

  • 相关阅读:
    山东大学软件学院项目实训-创新实训-网络安全靶场实验平台(十一)
    MySQL 是怎样运行的:单表访问方法及基于成本的优化
    刷题-买卖股票的最佳时机-C++/java(暴力法,动态规划,单调栈等)
    【C++之数组与指针】随机输入整数存入数组并用指针遍历
    如何应对访问国外服务器缓慢的问题?SDWAN组网是性价比之选
    【Mysql】Lock wait timeout exceeded; try restarting transaction
    数字ic设计|ASIC芯片开发过程
    pod 创建自定义库失败后解决方案
    微信小程序录音和头像上传
    python pycharm安装pexpect
  • 原文地址:https://blog.csdn.net/qq_37974755/article/details/126390449