设计模式-策略(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…...
国防科技大学计算机基础课程笔记02信息编码
1.机内码和国标码 国标码就是我们非常熟悉的这个GB2312,但是因为都是16进制,因此这个了16进制的数据既可以翻译成为这个机器码,也可以翻译成为这个国标码,所以这个时候很容易会出现这个歧义的情况; 因此,我们的这个国…...
在软件开发中正确使用MySQL日期时间类型的深度解析
在日常软件开发场景中,时间信息的存储是底层且核心的需求。从金融交易的精确记账时间、用户操作的行为日志,到供应链系统的物流节点时间戳,时间数据的准确性直接决定业务逻辑的可靠性。MySQL作为主流关系型数据库,其日期时间类型的…...
深入浅出Asp.Net Core MVC应用开发系列-AspNetCore中的日志记录
ASP.NET Core 是一个跨平台的开源框架,用于在 Windows、macOS 或 Linux 上生成基于云的新式 Web 应用。 ASP.NET Core 中的日志记录 .NET 通过 ILogger API 支持高性能结构化日志记录,以帮助监视应用程序行为和诊断问题。 可以通过配置不同的记录提供程…...
遍历 Map 类型集合的方法汇总
1 方法一 先用方法 keySet() 获取集合中的所有键。再通过 gey(key) 方法用对应键获取值 import java.util.HashMap; import java.util.Set;public class Test {public static void main(String[] args) {HashMap hashMap new HashMap();hashMap.put("语文",99);has…...
蓝牙 BLE 扫描面试题大全(2):进阶面试题与实战演练
前文覆盖了 BLE 扫描的基础概念与经典问题蓝牙 BLE 扫描面试题大全(1):从基础到实战的深度解析-CSDN博客,但实际面试中,企业更关注候选人对复杂场景的应对能力(如多设备并发扫描、低功耗与高发现率的平衡)和前沿技术的…...
什么是库存周转?如何用进销存系统提高库存周转率?
你可能听说过这样一句话: “利润不是赚出来的,是管出来的。” 尤其是在制造业、批发零售、电商这类“货堆成山”的行业,很多企业看着销售不错,账上却没钱、利润也不见了,一翻库存才发现: 一堆卖不动的旧货…...
生成 Git SSH 证书
🔑 1. 生成 SSH 密钥对 在终端(Windows 使用 Git Bash,Mac/Linux 使用 Terminal)执行命令: ssh-keygen -t rsa -b 4096 -C "your_emailexample.com" 参数说明: -t rsa&#x…...
初学 pytest 记录
安装 pip install pytest用例可以是函数也可以是类中的方法 def test_func():print()class TestAdd: # def __init__(self): 在 pytest 中不可以使用__init__方法 # self.cc 12345 pytest.mark.api def test_str(self):res add(1, 2)assert res 12def test_int(self):r…...
无人机侦测与反制技术的进展与应用
国家电网无人机侦测与反制技术的进展与应用 引言 随着无人机(无人驾驶飞行器,UAV)技术的快速发展,其在商业、娱乐和军事领域的广泛应用带来了新的安全挑战。特别是对于关键基础设施如电力系统,无人机的“黑飞”&…...
WEB3全栈开发——面试专业技能点P7前端与链上集成
一、Next.js技术栈 ✅ 概念介绍 Next.js 是一个基于 React 的 服务端渲染(SSR)与静态网站生成(SSG) 框架,由 Vercel 开发。它简化了构建生产级 React 应用的过程,并内置了很多特性: ✅ 文件系…...
