前言
上一章我们介绍了第一种设计模式单例模式,这一章我们将继续介绍一种新的设计模式,策略模式。在程序设计中,我们常常遇到这样的情况,实现同一个功能,但是可以使用不同的方法,这些算法灵活多样,可以互相交换使用,这就是本章要介绍的策略模式
正文
策略模式的定义
定义一系列算法,把它们一个个封装起来,并且使它们可以相互替换
这是关于策略模式的定义,策略模式是一种常用而且有效的设计模式,可以应用于有多个算法可以达到相同目的的情况。策略模式其实就是将一系列的算法封装起来,将程序中不变和易变的部分分开是每一种设计模式的共性,而策略模式就是将算法的实现与算法的调用分开的一种设计模式。下面我们会举例进一步介绍策略模式的应用
实现策略模式
这一小节我们将用例子进一步介绍策略模式的应用,我们先定义一个业务场景,假设产品提了一个需求,马上公司要发年终奖了,我们需要写一个工具类帮公司快速统计每个人的年终奖,假设目前有三个等级,S,A和B,他们分别可以拿的年终奖是4个月,3个月和2个月,这个几个月是基于他们自己的基本工资来决定的,所以我们这个工具类函数很明显需要两个参数,一个年终等级,一个基本薪资,很容易可以写出下面的代码
然后这个事情告一段落了,过了一段时间,产品说,诶咱又加了一个S+和C的绩效,要不再改改?那我们不得不找到这个工具类函数,接着之前的if继续往下迭代,这样是破坏了开放-封闭原则的,我们不知道会不会还有d,e,f的绩效,也不知道要加多少个if进去,这里我们就可以用策略模式去实现
很简单的,我们只要封装好绩效计算的算法函数,再传入工具类进行计算就可以,这样即使产品有一天要加新的绩效规则,我们也不需要修改工具类本身,而是只要再创建一个新的计算规则就可以了
这样我们只需要像S一样定义好策略函数引入工具类,再调用工具类的计算方法就可以获得这名员工的年终奖了,即使加个新的什么c,d,e,f的绩效咱也完全不慌,定义新的策略类传入就可以,这酸爽,妈妈再也不担心产品改需求了
javascript的策略模式
上面我们分离了策略和工具类,但是我们是基于类去实现的,前面几章节我们说到过javascript是一门无类语言,基于类去实现并没有必要,那是基于传统面向类的语言的做法,我们直接利用属性就可以实现这样的效果了
因为没有类的限制,所以js中可以用相对简短很多的代码去实现,这就是js作为一门脚本语言的优势了,上面的代码中,一样的,我们在需要调整策略的时候,只需要调整策略对象,而不需要操作到工具类函数,符合了单一职责原则
策略模式的优劣势
前面我们介绍了策略模式的相关知识和定义,这一部分我们来总结一下策略模式的优劣势,优势很明显:
- 可以有效的避免大量重复的条件语句,大家应该还记得之前我们最初的写法,对三种绩效使用了三次if语句,随着策略数目的变多,if语句的次数也会变多,会使得这个函数变得特立独行很难复用
- 提供了对开放-封闭原则的完美支持,前面我们利用策略模式将算法和算法执行的函数分离开来,两者互相不影响,算法部分的迭代并不会影响到算法执行的部分,每个部分都保持的单一的职责,所以也是符合单一职责原则的
- 这一点其实可能和第一点有点重复,就是策略模式可以使得函数具有极强的复用性,而不需要像使用大量if的时候,如果我们需要复用,只能将函数复制粘贴或者用import整段导入
但是凡事都是优势与劣势并存的,策略模式也有一些缺点,但是这些缺点相对来说没有那么严重:
- 使用策略模式会使得项目中额外多出很多策略类或者策略对象,但是对于大项目中未必不是好事,因为项目的分支更为细致清晰了,迭代也不会互相影响
- 这一点是基于js的实现导致的,我们知道js中不像java这些基于类的传统语言,没有类和接口的概念,对于我们之前定义的一些策略对象,没办法在代码编译层次上加上一些限制,不能保证一些必须的方法必定被实现,只能依靠程序员自觉或者在代码层次上加上对没有这些方法抛出错误的限制,如果在需求迭代中,一个粗心的程序员在别人的策略类上想加一个新的策略但是没有实现一些必备的方法,那么在调用工具类的时候便会出现一些意外的错误
小结
策略模式是一种常见而且有效的设计模式,它可以帮助我们有效分离算法和算法执行的部分,在传统面向类语言中,策略模式基于策略类去实现,但是js中,我们可以用函数去代替类,起到一个简化策略模式的作用。
但是也因为这种简化,导致没办法像面向类语言一样利用接口或者抽象类去增加对策略类必须实现的函数的限制,也可能因为此增加对工具类调用的报错,这就需要我们多一点细心或者在代码层次或者注释层次上去补充这种限制来减少不必要的报错
小伙伴们今天的学习就到这里了,如果觉得本文对你有帮助的话,欢迎转发,评论,收藏,点赞!!!