用了策略模式之后,再也不用写那么多 if else 了,真香!
前言
从我个人理解来看,设计模式
其实就藏在我们平时的代码中,只是有人把它们提、炼出来,赋予了一些专业的名词和定义,下面给大家介绍一个日常项目开发中非常实用的设计模式,也就是策略模式
。
策略模式的定义
先来看下策略模式的定义:定义一系列的算法,把它们一个个封装起来,并且使它们可以相互替换。
简单来说就是有多种选择
,然后一般只会选择一种
。从代码的角度来说就是,定义一系列的if
和elseif
,然后只会命中其中一个。
举个例子
话不多说,直接来看例子,比如我们需要计算员工工资,员工工资计算规则如下:
- 高级工:时薪为25块/小时
- 中级工:时薪为20块/小时
- 初级工:时薪为15块/小时
按每天10小时的工作时长来算。
一、第一版实现:
const calculateSalary = function (workerLevel, workHours = 10) {
if (workerLevel === 'high') {
return workHours * 25
}
if (workerLevel === 'middle') {
return workHours * 20
}
if (workerLevel === 'low') {
return workHours * 15
}
}
console.log(calculateSalary('high')) // 250
console.log(calculateSalary('middle')) // 200
这段代码具有明显的缺点:
- calculateSalary函数庞大,有许多的if else语句,这些语言需要覆盖所有的逻辑分支
- calculateSalary函数缺乏弹性,如果新增一种员工等级higher,需要修改calculateSalary函数的内部实现,违反
开放——封闭原则
。 - 算法的复用性差
二、第二版实现(函数组合):
当然,我们可以使用函数组合的方式重构代码,把每一个if中的逻辑单独抽离成一个函数。
const workerLevelHigh = function (workHours) {
return workHours * 25
}
const workerLevelMiddle = function (workHours) {
return workHours * 20
}
const workerLevelLow = function (workHours) {
return workHours * 15
}
const calculateSalary = function (workerLevel, workHours = 10) {
if (workerLevel === 'high') {
return workerLevelHigh(workHours)
}
if (workerLevel === 'middle') {
return workerLevelMiddle(workHours)
}
if (workerLevel === 'low') {
return workerLevelLow(workHours)
}
}
console.log(calculateSalary('high', 10)) // 250
console.log(calculateSalary('middle', 10)) // 200
这样会提高算法的复用性,但这种改善十分有限,calculateSalary函数
依旧庞大和缺乏弹性。
三、第三版实现(策略模式):
我们可以把不变的部分和变化的部分拆分开来。
- 不变的部分:算法的使用方式不变,都是根据某个算法取得计算后的工资数额;
- 变化的部分:算法的实现。
我们js的对象是key value
的形式,这可以帮助我们天然的替换掉if else
。
因此,我们可以定义对象的两部分:
- 针对变化的部分,我们可以定义一个策略对象,它封装了具体的算法,负责具体的计算过程
- 针对不变的部分,我们提供一个Context函数,它接受客户的请求,随后把请求委托给策略对象。
const strategies = {
"high": function (workHours) {
return workHours * 25
},
"middle": function (workHours) {
return workHours * 20
},
"low": function (workHours) {
return workHours * 15
},
}
const calculateSalary = function (workerLevel, workHours) {
return strategies[workerLevel](workHours)
}
console.log(calculateSalary('high', 10)) // 250
console.log(calculateSalary('middle', 10)) // 200
策略模式的优缺点
从我个人在实际项目中的使用来看,策略模式的优缺点如下:
优点:
- 代码复杂度降低:再也不用写那么多if else了。
eslint
其中有一项规则配置叫圈复杂度
,其中一条分支也就是一个if会让圈复杂增加1,圈复杂度高的代码不易阅读和维护,用策略模式
就能很好的解决这个问题; - 易于切换、理解和扩展:它将算法封装在独立的strategy中,比如你要在上面代码中加一个等级
higher
或lower
,直接更改策略对象strategies
就行,十分方便。 - 复用性高:策略模式中的算法可以复用在系统的其它地方,你只需要用将策略类
strategies
用export或者module.exports导出,就能在其他地方很方便的复用。
缺点:
- 增加使用者使用负担:因为大量运用
策略模式
会在实际项目中堆砌很多策略类或者策略对象
,这样项目的新人如果不熟悉这些策略类和策略对象
,会增加他们的使用成本和学习成本,前期来说会比看if else
更加难懂。
小结
以上就是我个人对策略模式
的解读和了解啦,实际上项目中用策略模式的场景还是挺多的,因为在写业务代码中,很容易写出大量的if else,这时候就可以封装为策略模式
,方便项目维护和扩展,从我个人的使用体验来看,还是相当香的。
大家喜欢在实际项目使用策略模式
么,欢迎留言和讨论~
作者:han_
来源:juejin.cn/post/7279041076273610764
来源:juejin.cn/post/7279041076273610764