设计模式-策略(Strategy)模式
- 又被称为政策(方针)模式
- 策略模式(Strategy Design Pattern):封装可以互换的行为,并使用委托来决定要使用哪一个
- 策略模式是一种行为设计模式,它能让你定义一系列算法,并将每种算法分别放入独立的类中,以使算法的对象能够相互替换
- 用人话翻译后就是:运行时我给你这个类的方法传不同的 “key”,你这个方法就去执行不同的业务逻辑
- 解释:
- 现实世界例子:屠龙是一项危险的职业;有经验将会使它变得简单;经验丰富的屠龙者对不同类型的龙有不同的战斗策略
- 直白点说,策略模式允许在运行时选择最匹配的算法
- 在程序编程领域,策略模式(又叫政策模式)是一种启用在运行时选择算法的行为型软件设计模式
- 仔细一想,这不就是 if else 干的事吗
- 先直观的看下传统的多重 if else 代码:

- 再来看策略模式类图:

- 策略模式涉及到三个角色:
- Strategy:策略接口或者策略抽象类,用来约束一系列的策略算法(Context 使用这个接口来调用具体的策略实现算法)
- ConcreateStrategy:具体的策略类(实现策略接口或继承抽象策略类)
- Context:上下文类,持有具体策略类的实例,并负责调用相关的算法
- 先来看看最简单的策略模式 demo:
- 1-策略接口(定义策略)

- 2-具体的算法实现

- 3-上下文的实现

- 4-客户端使用(策略的使用)

- 这种策略的使用方式其实很死板,真正使用的时候如果还这么写,和写一大推 if-else 没什么区别,所以我们一般会结合工厂类,在运行时动态确定使用哪种策略
- 策略模式侧重如何选择策略、工厂模式侧重如何创建策略
- 策略模式的功能就是把具体的算法实现从具体的业务处理中独立出来,把它们实现成单独的算法类,从而形成一系列算法,并让这些算法可以互相替换
- 策略模式的重心不是如何来实现算法,而是如何组织、调用这些算法,从而让程序结构更灵活,具有更好的维护性和扩展性
- 实际上,每个策略算法具体实现的功能,就是原来在 if-else 结构中的具体实现,每个 if-else 语句都是一个平等的功能结构,可以说是兄弟关系
- 策略模式呢,就是把各个平等的具体实现封装到单独的策略实现类了,然后通过上下文与具体的策略类进行交互
- 策略模式 = 实现策略接口(或抽象类)的每个策略类 + 上下文的逻辑分派

- 策略模式的本质:分离算法,选择实现
- 所以说,策略模式只是在代码结构上的一个调整,即使用了策略模式,该写的逻辑一个也少不了,到逻辑分派的时候,只是变相的 if-else
- 而它的优化点是抽象了出了接口,将业务逻辑封装成一个一个的实现类,任意地替换
- 在复杂场景(业务逻辑较多)时比直接 if-else 更好维护和扩展些
- 在策略模式中,我们可以自己定义谁来选择具体的策略算法,有两种:
- 客户端:当使用上下文时,由客户端选择,像我们上边的 demo
- 上下文:客户端不用选,由上下文来选具体的策略算法,可以在构造器中指定
- 避免冗长的if/else:
- 比如在出门旅游时:路线、交通工具的类型、天数、舱位等级、餐饮、住宿等等
- 每个节点在执行时,都需要根据预算进行不同的操作,从而引起大量的判断
- 增加一个策略,修改一个策略,都有可能牵一发而动全身
- 需要对所有状态进行回测

- 整个业务如图所示,所有的判断都耦合在业务流程内部,牵一发而动全身

- 使用策略模式
- 我们可以将某一条件(Type)下的逻辑,聚合封装到具体的策略类中

- 使用策略类后如图所示,每个的情况被封装聚合到单个策略类中,相互隔离

- 所以策略模式的作用主要体现在:
- 1-解耦策略的定义、创建和使用
- 控制代码的复杂度,让每个部分都不至于过于复杂、代码量过多
- 2-让复杂框架满足开闭原则
- 添加或者修改新策略的时候,最小化、集中化代码改动,减少引入 bug 的风险
- 策略的创建
- 通常会通过类型(type)来判断创建哪个策略来使用
- 这里,有两种创建方式
- if-else创建
- 适用于有状态的策略类,每次创建一个新的策略类给业务方使用

- 通过工厂模式里的Map进行创建
- 适用于无状态的策略类创建,大家共用一个策略类即可

- 本质上讲,是借助“查表法”,根据 type 查表替代根据 type 分支判断
- Java中的例子:
- 采用 Comparator 参数的 Collections.sort() 方法;根据 Comparator 接口的不同实现,对象会以不同的方式进行排序
- 使用策略模式应当:
- 许多相关的类只是行为不同;策略模式提供了一种为一种类配置多种行为的能力
- 你需要一种算法的不同变体;比如,你可能定义反应不用时间空间权衡的算法;当这些算法的变体使用类的层次结构来实现时就可以使用策略模式
- 一个算法使用的数据客户不应该对其知晓;使用策略模式来避免暴露复杂的,特定于算法的数据结构
- 一个类定义了许多行为,这些行为在其操作中展现为多个条件语句;移动相关的条件分支到它们分别的策略类中来代替这些条件语句
相关文章:
设计模式-策略(Strategy)模式
又被称为政策(方针)模式策略模式(Strategy Design Pattern):封装可以互换的行为,并使用委托来决定要使用哪一个策略模式是一种行为设计模式,它能让你定义一系列算法,并将每种算法分别放入独立的类中&#x…...
Star 4.1k!Gitee GVP开源项目!新一代桌面应用开发框架 ElectronEgg!
前言 随着现代技术的快速升级迭代及发展,桌面应用开发已经变得越来越普及。然而对于非专业桌面应用开发工程师在面对这项任务时,可能会感到无从下手,甚至觉得这是一项困难的挑战。 本篇文章将分享一种新型桌面应用开发框架 ElectronEgg&…...
node.js学习(简单聊天室)
在掘金查看该文章 1. TCP服务搭建 1.1 socket 先来粗略了解下socket 套接字(socket)是一个抽象层,应用程序可以通过它发送或接收数据,可对其进行像对文件一样的打开、读写和关闭等操作。套接字允许应用程序将I/O插入到网络中&am…...
cfa一级考生复习经验分享系列(四)
备考CFA一级满打满算用了一个多月,每天八个小时以上。可能如果仅以通过为目标的话完全不用这样,看过太多类似于只看了一周就通过了考试又或是放弃了好几门飘过了考试的情况,我觉得这是不正确的考试状态,完全不必惊叹,踏…...
PPT插件-好用的插件-放映笔、绘图板-大珩助手
放映笔 幻灯片放映时,工具在幻灯片的左下方,本工具在幻灯片的右侧,可以移动,可以方便在右侧讲课时候使用 绘图板 可在绘图板上写签名、绘制图画、写字等等,点画笔切换橡皮擦,点插入绘图,将背景…...
弧形导轨的安装注意事项
随着弧形导轨的应用日渐普遍,在日常使用中总会遇到很多各种各样的问题,原因很多是安装不正确或者使用不恰当。不合理的使用不但不能充分发挥其价值还会导致使用寿命大打折扣,使企业造成不必要的损失,因此大伙有必要了解一些安装的…...
Elasticsearch优化-04
Elasticsearch优化 1、优化-硬件选择 Elasticsearch 的基础是 Lucene,所有的索引和文档数据是存储在本地的磁盘中,具体的路径可在 ES 的配置文件…/config/elasticsearch.yml中配置,如下: # #Path to directory where to store …...
Springboot+vue的公寓报修管理系统(有报告)。Javaee项目,springboot vue前后端分离项目
演示视频: Springbootvue的公寓报修管理系统(有报告)。Javaee项目,springboot vue前后端分离项目 项目介绍: 本文设计了一个基于Springbootvue的前后端分离的公寓报修管理系统,采用M(model&…...
uniapp腾讯地图路线规划
在uniapp中使用腾讯地图进行路线规划需要通过腾讯地图API进行操作。以下是基本的步骤: 在腾讯地图开放平台上注册账号,并创建应用获取API key。 在uniapp的项目中引入腾讯地图API的JS文件,例如在index.html中添加以下代码: <…...
Python 全栈体系【四阶】(五)
第四章 机器学习 三、数据预处理 1. 数据预处理的目的 去除无效数据、不规范数据、错误数据 补齐缺失值 对数据范围、量纲、格式、类型进行统一化处理,更容易进行后续计算 2. 预处理方法 2.1 标准化(均值移除) 让样本矩阵中的每一列的…...
原点处可微问题
文章目录 原点可微问题例例 原点可微问题 lim x → 0 , y → 0 f ( x , y ) − f ( 0 , 0 ) x 2 y 2 \lim\limits_{x\to{0},y\to{0}} \frac{f(x,y)-f(0,0)}{\sqrt{x^2y^2}} x→0,y→0limx2y2 f(x,y)−f(0,0) 0 0 0(1)是函数 f ( x , y ) f(x,y) f(x,y)在 ( 0 , 0 ) (…...
Flink+Kafka消费
引入jar <dependency><groupId>org.apache.flink</groupId><artifactId>flink-java</artifactId><version>1.8.0</version> </dependency> <dependency><groupId>org.apache.flink</groupId><artifactI…...
Seconds_Behind_Master越来越大,主从同步延迟
问题现象 发现从库mysql_slave的参数Seconds_Behind_Master越来越大。已排除主从服务器时间不一致;那么主要就判断两点:是io thread慢还是 sql thread慢?先观察show slave status\G 。 判断3个参数(参数后面的值是默认空闲时候的…...
除法求值[中等]
一、题目 给你一个变量对数组equations和一个实数值数组values作为已知条件,其中equations[i] [Ai, Bi]和values[i]共同表示等式Ai / Bi values[i]。每个Ai或Bi是一个表示单个变量的字符串。另有一些以数组queries表示的问题,其中queries[j] [Cj, Dj…...
新时代商业市场:AR技术的挑战与机遇并存
随着科技的不断发展,增强现实(AR)技术逐渐成为当今社会的一个重要组成部分。AR技术能够将虚拟世界与现实世界相结合,为人们提供更加丰富、多样化的体验。在新时代的社会商业市场中,AR技术也正逐渐被应用于各种商业活动…...
RHEL8中ansible的使用
编写ansible.cfg和清单文件ansible的基本用法 本章实验三台RHEL8系统(rhel801,rhel802,rhel803),其中rhel801是ansible主机 这里要确保ansible主机能够解析所有被管理的机器,这里通过配置/etc/hosts来实现…...
【1.6计算机组成与体系结构】存储系统
目录 1.层次化存储结构2.Cache2.1 Cache的介绍2.2 局部性原理2.3 Cache应用 1.层次化存储结构 由 ⬆ CPU:寄存器。 快 ⬆ Cache:按内容存取(相联存储器)。 到 ⬆内存(主存):DRAM。 慢 ⬆ 外存(辅存&#…...
TCP/UDP 协议
目录 一.TCP协议 1.介绍 2.报文格式 编辑 确认号 控制位 窗口大小 3.TCP特性 二.TCP协议的三次握手 1.tcp 三次握手的过程 三.四次挥手 2.有限状态机 四.tcp协议和udp协议的区别 五.udp协议 UDP特性 六.telnet协议 一.TCP协议 1.介绍 TCP(Transm…...
如何正确理解和使用 Golang 中 nil ?
目录 指针中的 nil 切片中的 nil map 中的 nil 通道中的 nil 函数中的 nil 接口中的 nil 避免 nil 相关问题的最佳实践 小结 在 Golang 中,nil 是一个预定义的标识符,在不同的上下文环境中有不同的含义,但通常表示“无”、“空”或“…...
IDEA新建jdk8 spring boot项目
今天新建spring boot项目发现JDK版本最低可选17。 但是目前用的最多的还是JDK8啊。 解决办法 Server URL中设置: https://start.aliyun.com/设置完成后,又可以愉快的用jdk8创建项目了。 参考 https://blog.csdn.net/imbzz/article/details/13469117…...
用 LangChain 克隆一个 ChatGPT:LLMChain + Memory 实战
0 前言 ChatGPT 之所以好用,核心在于: 个性化的系统提示词多轮对话记忆 本文基于 LangChain,用不到 30 行代码复刻这两个能力,构建一个可自定义人格的对话 AI。 1 技术栈组件说明LLMChainLangChain 的核心链,将 LLM、P…...
从收音机到5G:OFDM技术的前世今生,以及它为何成为Wi-Fi和5GNR的基石
从收音机到5G:OFDM技术的前世今生,以及它为何成为Wi-Fi和5GNR的基石 想象一下,你正用手机流畅播放4K视频,同时下载大文件——这背后是一套诞生于上世纪60年代的技术在支撑。OFDM(正交频分复用)的传奇之处在…...
用手机遥控电脑演讲:开源项目Presentation-Control部署与实战指南
1. 项目概述与核心价值最近在准备一个重要的线上技术分享,过程中遇到了一个几乎所有演讲者都会头疼的问题:如何优雅地控制幻灯片播放,同时又能自如地操作电脑上的其他演示工具,比如代码编辑器、终端或者在线Demo?传统的…...
逆向工程实现GitHub Copilot HTTP API:解锁AI代码补全的无限集成可能
1. 项目概述:一个反向工程的“桥梁”如果你是一名开发者,并且对 GitHub Copilot 的智能代码补全能力印象深刻,但同时又希望能在自己偏爱的编辑器、IDE,甚至是命令行工具里直接调用它的能力,那么purocean/expose-github…...
STM32H7硬件JPEG编码实战:从RGB565到JPEG文件,一个完整项目的避坑记录
STM32H7硬件JPEG编码实战:从RGB565到JPEG文件的完整避坑指南 在嵌入式图像处理领域,实时压缩摄像头采集的原始图像数据一直是个挑战。STM32H7系列凭借其内置的硬件JPEG编解码器(HJPEG),为开发者提供了高效的解决方案。…...
LeetCode 118. 杨辉三角
给定一个非负整数 numRows,生成「杨辉三角」的前 numRows 行。在「杨辉三角」中,每个数是它左上方和右上方的数的和。示例 1:输入: numRows 5 输出: [[1],[1,1],[1,2,1],[1,3,3,1],[1,4,6,4,1]]示例 2:输入: numRows 1 输出: [[1]]提示:1 < numRows…...
Ansible file模块实战:从创建目录到管理软硬链接,一篇搞定Linux文件系统日常运维
Ansible file模块实战:从创建目录到管理软硬链接,一篇搞定Linux文件系统日常运维 在当今云计算和自动化运维的时代,手动登录服务器执行文件操作已经成为效率的瓶颈。想象一下,当你需要在数百台服务器上统一创建应用目录结构、批量…...
运动分析革命:如何用Kinovea将视频变成精准的教练和研究员
运动分析革命:如何用Kinovea将视频变成精准的教练和研究员 【免费下载链接】Kinovea Video solution for sport analysis. Capture, inspect, compare, annotate and measure technical performances. 项目地址: https://gitcode.com/gh_mirrors/ki/Kinovea …...
IoT产品创新方法论:构建“场景 × 技术 × 数据 × 商业”的系统创新能力
目录 一、 问题与背景 二、 本文将系统讲解 三、 什么是IoT产品创新 3.1 核心定义 3.2 IoT创新的核心变化 3.3 创新的三种层级(阶梯论) 四、 IoT产品创新结构模型(核心框架) 4.1 四维创新模型(核心体系) 4.2 创新演进路径 五、 五大IoT创新方法论(核心武器库)…...
2026届学术党必备的AI写作网站实测分析
Ai论文网站排名(开题报告、文献综述、降aigc率、降重综合对比) TOP1. 千笔AI TOP2. aipasspaper TOP3. 清北论文 TOP4. 豆包 TOP5. kimi TOP6. deepseek 作为学术研究启动时核心的前置材料的开题报告,要完成文献梳理,要搭建…...
