策略模式的应用(省去一系列的`if`和`elseif`)

目录

前言

从我个人理解来看,设计模式其实就藏在我们平时的代码中,只是有人把它们提、炼出来,赋予了一些专业的名词和定义,下面给大家介绍一个日常项目开发中非常实用的设计模式,也就是策略模式

策略模式的定义

先来看下策略模式的定义:定义一系列的算法,把它们一个个封装起来,并且使它们可以相互替换。

简单来说就是有多种选择,然后一般只会选择一种。从代码的角度来说就是,定义一系列的ifelseif,然后只会命中其中一个。

举个例子

话不多说,直接来看例子,比如我们需要计算员工工资,员工工资计算规则如下:

  • 高级工:时薪为25块/小时
  • 中级工:时薪为20块/小时
  • 初级工:时薪为15块/小时

按每天10小时的工作时长来算。

一、第一版实现:

js 复制代码
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中的逻辑单独抽离成一个函数。

js 复制代码
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函数,它接受客户的请求,随后把请求委托给策略对象。
js 复制代码
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中,比如你要在上面代码中加一个等级higherlower,直接更改策略对象strategies就行,十分方便。
  • 复用性高 :策略模式中的算法可以复用在系统的其它地方,你只需要用将策略类strategies用export或者module.exports导出,就能在其他地方很方便的复用。

缺点:

  • 增加使用者使用负担 :因为大量运用策略模式会在实际项目中堆砌很多策略类或者策略对象,这样项目的新人如果不熟悉这些策略类和策略对象,会增加他们的使用成本和学习成本,前期来说会比看if else更加难懂。

小结

以上就是我个人对策略模式的解读和了解啦,实际上项目中用策略模式的场景还是挺多的,因为在写业务代码中,很容易写出大量的if else,这时候就可以封装为策略模式,方便项目维护和扩展,从我个人的使用体验来看,还是相当香的。

大家喜欢在实际项目使用策略模式么,欢迎留言和讨论~

相关推荐
侃侃_天下2 天前
最终的信号类
开发语言·c++·算法
echoarts2 天前
Rayon Rust中的数据并行库入门教程
开发语言·其他·算法·rust
Aomnitrix2 天前
知识管理新范式——cpolar+Wiki.js打造企业级分布式知识库
开发语言·javascript·分布式
每天回答3个问题2 天前
UE5C++编译遇到MSB3073
开发语言·c++·ue5
伍哥的传说2 天前
Vite Plugin PWA – 零配置构建现代渐进式Web应用
开发语言·前端·javascript·web app·pwa·service worker·workbox
小莞尔2 天前
【51单片机】【protues仿真】 基于51单片机八路抢答器系统
c语言·开发语言·单片机·嵌入式硬件·51单片机
我是菜鸟0713号2 天前
Qt 中 OPC UA 通讯实战
开发语言·qt
JCBP_2 天前
QT(4)
开发语言·汇编·c++·qt·算法
Brookty2 天前
【JavaEE】线程安全-内存可见性、指令全排序
java·开发语言·后端·java-ee·线程安全·内存可见性·指令重排序
百锦再2 天前
[特殊字符] Python在CentOS系统执行深度指南
开发语言·python·plotly·django·centos·virtualenv·pygame