【面试题】什么是策略模式?用了策略模式之后,再也不用写那么多 if else 了,真香!

简介: 【面试题】什么是策略模式?用了策略模式之后,再也不用写那么多 if else 了,真香!

给大家推荐一个实用面试题库

1、前端面试题库 (面试必备)            推荐:★★★★★

地址:web前端面试题库

前言

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

策略模式的定义

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

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

举个例子

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

  • 高级工:时薪为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中,比如你要在上面代码中加一个等级higherlower,直接更改策略对象strategies就行,十分方便。
  • 复用性高:策略模式中的算法可以复用在系统的其它地方,你只需要用将策略类strategies用export或者module.exports导出,就能在其他地方很方便的复用。

缺点:

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

小结

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

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

给大家推荐一个实用面试题库

1、前端面试题库 (面试必备)            推荐:★★★★★

地址:web前端面试题库

相关文章
|
关系型数据库 MySQL 数据库
Mysql数据库redo log及binlog的写入
Mysql数据库redo log及binlog的写入
|
测试技术 数据库
腾讯游戏测试工程师的经验心得分享
腾讯游戏测试工程师的经验心得分享
644 0
|
JSON JavaScript Linux
【MCP教程系列】如何自己打包MCP服务并部署到阿里云百炼上
本文章以阿里云百炼的工作流为例,介绍如何将其封装为MCP服务并部署到平台。主要步骤包括:1)使用Node.js和TypeScript搭建MCP服务;2)将项目打包并发布至npm官方平台;3)在阿里云百炼平台创建自定义MCP服务;4)将服务添加到智能体中进行测试。通过这些步骤,您可以轻松实现工作流的MCP化,并在智能体中调用自定义服务。
3346 0
|
9月前
|
机器学习/深度学习 资源调度 算法
机器学习领域必知数学符号与概念(一)
本文介绍了一些数学符号以及这些符号的含义。
745 65
|
8月前
|
安全 算法 物联网
SSL/TLS:互联网通信的加密基石与安全实践
**简介:** 在数字化时代,互联网每天传输海量敏感数据,网络攻击频发。SSL/TLS协议作为网络安全的基石,通过加密技术确保数据安全传输。本文解析SSL/TLS的技术架构、密码学原理、应用场景及常见误区,探讨其在未来的发展趋势,强调持续演进以应对新型威胁的重要性。 SSL/TLS不仅保障Web安全,还广泛应用于API、邮件、物联网等领域,并遵循合规标准如PCI DSS和GDPR。
|
监控 安全 项目管理
项目成功秘诀:高效管理策略确保按时交付
项目成功对企业生存发展至关重要,需要明确目标和范围,运用SMART原则和设计思维确保目标与市场需求相符。通过工作分解、优先级排序管理需求,建立变更和风险管理流程。制定详细项目计划,考虑约束条件、关键节点和风险。优化团队协作,明确角色责任,建立有效沟通机制,激励团队成员。实施PDCA循环控制项目进程,关注交付和复盘,以实现高质量的项目成果。
605 1
|
Java jenkins 网络安全
从零搭建 Gerrit 实现 code review
从零搭建 Gerrit 实现 code review
348 1
|
小程序 JavaScript 开发者
微信小程序分包的相关概念和使用
本文介绍了微信小程序分包的概念、优势、配置方法、加载规则、体积限制,以及独立分包和分包预下载的配置,旨在帮助开发者优化小程序的加载速度和开发效率。
|
JavaScript 容器
富文本的图片添加点击放大功能
思路:富文本加载后,dom出全部img元素,然后各自单独添加点击事件
485 3
|
Python
Python pkgutil基础使用说明
pkgutil是Python的标准库中的一个模块,提供了一系列与包(Package)相关的工具函数,例如动态加载包、递归遍历包内的子模块等。在本篇教程中,我们将带你详细了解pkgutil模块的主要功能及使用方法。
269 2