无所谓,策略模式会出手——策略模式的世界里为什么可以没有if和else?

13 篇文章 2 订阅
10 篇文章 0 订阅


前言

最近偶然间看到部分框架的源码(名字已经记不清了),加上最近抖音老是给我推策略模式相关视频,结合自己的学习后,
发现自己很多的代码其实可以写的更加优雅
在此整理为一篇对业务中实际常见业务场景有帮助的博客,自己也在慢慢学习把这种思路结合到自己的业务代码中,
当然,更重要的是思路,写下此篇博客,希望以后回头看的时候会有所感悟。


一、Vue3为什么取消了filterAPI?

filter在Vue2里面是我们处理数据很常见的一个语法,但是在Vue3里面目前已经被废弃了,废弃的原因就是为了精简代码,某种程度上它能做到的methods计算属性也能实现。这跟我们今天策略模式在代码中体现的能力高度重合。好了,接下来就是干货了

二、策略模式简介

策略模式是设计模式中一种设计方案,对应的设计模式一共有23种,又分为三大类

  1. 创建型模式(工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式)
  2. 结构性模式(适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。)
  3. 行为型模式(策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式)

这些模式可能穷极一生也学不完,博主也只是简单的列一下,感兴趣的兄弟们可以私下了解一下。
我们今天的主题是行为型模式中的策略模式
策略模式之所以被称为行为型模式,
可以把之理解为。我们正常编码中,假设一个人需要去为爱冲锋,
那么在我们的编码里他首先要先去骑自行车,然后骑了5分钟,碰到事件(轮胎坏了),这个时候我们就要再去写代码去处理这个事件,而后再骑了几个小时,碰到事件(肚子饿了),我们则需要写其它的代码来处理之类的事情

策略模式不一样,策略模式为定义一系列的算法,把他们一个个的封装起来,并使他们可以互相替换
如果我们用策略模式来冲锋,即为定义好一系列可能会出现的事件,这个策略模式触发之后5分钟会自动修轮胎,几小时后会自动吃饭,直接让对应的策略更改为去冲锋,即可完成对应事件,它更重要的是一个编程思想

三、如何用策略模式在业务中优化我们的if和else代码

拿业务中比较常见的if和else情况举例,博主将逐步优化这个代码来体现策略模式如何使代码变得更优雅

<script>
    function blogTest(value){
      if(value==='桔梗'){
        console.log('桔梗送出一支');
      }else if(value==='红玫瑰'){
        console.log('桔梗送出一支');
      }else if(value==='香槟玫瑰'){
        console.log('桔梗送出一支');
      }else if(value==='月季'){
        console.log('桔梗送出一支');
      }
    }
    blogTest('桔梗')
    //输出结果:桔梗送出一支
</script>

首先可以利用对象的数据结构特性,把这段代码简单的改造一下

<script>
   function blogTest(value){
      let tempObj={
        '桔梗':()=>console.log('桔梗送出一支'),
        '红玫瑰':()=>console.log('红玫瑰送出一支'),
        '香槟玫瑰':()=>console.log('香槟玫瑰送出一支'),
        '月季':()=>console.log('月季送出一支'),
        '丁香花':()=>console.log('丁香花送出一支')
      };
      tempObj[value]()
      // 输出结果 桔梗送出一支
    }
    blogTest('桔梗')
</script>

我们把它改成引用对象+函数调用的方式,这样拓展性比较好,而且更加简洁易于拓展,并且可以自己加上业务中的参数中执行不同的逻辑,还没完,那么如果我们业务中判断条件并不一致的情况下的if语句,我们可以用策略模式来优化吗?
答案依然是可以的

 	function blogTest(value){
      if(value[0]=='花'){
        console.log('第一个是花')
      }else if(value.includes('桔')){
        console.log('包含了桔')
      }else if(value.endsWith('花')&& value.includes('玫瑰')){
        console.log('最后一个是花并且包含了玫瑰')
      }
      // 输出结果 最后一个是花并且包含了玫瑰
    }
    blogTest('玫瑰花')

我们仍然沿用策略模式的设计思路,把这个方法进行改造,改造之后为

function blogTest(value){
      const tempMap=[
        [
          ()=>value[0]==='花',
          ()=>console.log('第一个是花')
        ],
        [
          ()=>value.includes('桔'),
          ()=>console.log('包含了桔')
        ],
        [
          ()=>value.endsWith('花')&& value.includes('玫瑰'),
          ()=>console.log('最后一个是花并且包含了玫瑰')
        ]
      ];
      const res= tempMap.find(m=>m[0]());
      res?res[1]():console.log('没找到对应方法');
    }
    // 运行结果:最后一个是花并且包含了玫瑰
    blogTest('玫瑰花')

这个思路即是利用元组的数据结构特性,先去执行数组集合下标0的方法,这个时候运行是会默认带上函数参数的,如果符合对应条件,去执行下标为1的方法,一般不复杂的使用上面两种即可,以上三种可以满足99.9%的业务需求,当然更重要的是思路。
Nest.js源码里面用了大量的这种模式进行编码,这个函数在我们的实际项目中,可以封装为对应的Js文件进行暴露,匿名函数也可以修改为具名函数,便于阅览。

总结

值得注意的是,代码优雅的同时肯定会损耗一部分性能,但是我们实际上开发是远远达不到这个瓶颈的。
毕竟追求性能的话无限switch和case就好了。我个人的侧重点还是在代码优雅易于阅览这个点上
好记性不如烂笔头
随时随地给自己对项目的状态进行实时的记录,想来以后回忆起来也是极美的

明天,又是充满希望的一天!

最后放上一张镇楼图
在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值