状态模式和策略模式对比

news2025/1/19 11:20:14

状态模式和策略模式都是行为型设计模式,它们的主要目标都是将变化的行为封装起来,使得程序更加灵活和可维护。之所以将状态模式和策略模式进行比较,主要是因为两个设计模式的类图相似度较高。但是,从状态模式和策略模式的应用场景来说,两个模式存在显著的差异。接下来将一步步说明。

状态模式

状态模式是一种行为设计模式,允许一个对象在其内部状态改变时改变它的行为,使其看起来修改了自身所属的类。状态模式的本质是将状态对象化处理。其类图表示如下:

请添加图片描述

状态模式主要适用于状态数量非常多且状态相关的代码会频繁变更的话,或代码中包含大量与对象状态有关的条件语句,或基于条件的状态机转换中存在许多重复代码等场景。通过将状态相关的代码抽取到状态类中,实现了状态与状态上下文的解耦。这样,就可在不修改已有状态类和上下文的前提下,引入新状态,这符合面向对象的开闭原则。但是,状态模式因为将状态对象化处理,也会带来代码复杂度上升的问题。如果只有很少的几个状态,或者状态很少发生变化,则不建议使用状态模式。此外,虽然引入新状态可以不用修改已有状态类和上下文,但是增加新的状态类需要修改那些负责状态转换的源代码,这无疑违背“开闭”原则。

策略模式

策略模式也是一种行为设计模式,策略模式通过定义一组可相互替换的算法,实现将算法独立于使用它的用户而变化。简单来说,就是定义一系列算法,然后将每一个算法封装起来,并使它们可相互替换。其类图表示如下:

请添加图片描述

从策略模式的类图可知,策略模式就是抽象了算法,并通过策略上下文完成了具体算法策略的选择。
策略模式适用于一个行为有多种实现、或为了消除复杂的条件运算符(如多重的条件选择语句),实现同一算法在不同变体中切换等场景。策略模式将算法的实现独立出来,实现了在不修改原有系统的基础上选择算法或行为,这符合开闭原则。此外,策略模式还可消除多重条件语句,降低代码复杂度。与其他设计模式一样,策略模式因为需要引入新的算法接口和实现,会带来代码复杂度上升的问题。策略模式虽然可以在不修改原有系统的基础上选择算法或行为,但是新增一个算法实现,仍需要修改策略上下文。而且,对于条件语句少的场景或算法极少变化的场景下,没有必要引入策略模式。

状态模式和策略模式的对比

无论状态模式,还是策略模式,都是创建型模式。其主要职责都是将变化的行为封装起来,使得程序更加灵活和可维护。状态模式主要用于处理一个对象在其内部状态改变时,需要改变其行为的情况。状态模式通过将状态相关的代码抽取到状态类中,实现了状态与状态上下文的解耦。在对象有多个状态,且状态之间存在复杂的转换逻辑时,状态模式可以简化代码和提高可维护性。而策略模式通过定义一组可相互替换的算法(算法簇),实现将算法独立于使用它的用户而变化。从功能上来说,状态模式和策略完全是两个完全不相似的设计模式。
接下来重点分析状态模式和策略模式的结构。从类图结构上看,策略模式和状态模式很相似。都有Context,且这个Context都依赖抽象的状态或策略。且抽象的状态或策略都有多种实现。但是,两个设计模式也仅仅是类图相似,其职责完全不同。在状态模式中,StateContext保存了State对象(具体状态对象)的引用,并将所有与该状态相关的工作委派给它。而在策略模式中,StrategyContext维护指向Strategy对象(具体策略)的引用,且仅通过策略接口与该对象进行交流。在状态模式中,多个State对象可能存在交互(如从状态A切换到状态B)。而在策略模式中,每个Strategy对象都不需要感知其他Strategy对象的存在(每个Strategy子类都是行为的封装)。策略模式偏重于可替换的算法以及这些算法在对应的Context中的正确调用,而状态模式则偏重于各状态自身的逻辑运行以及各个状态间的切换和初始化。
对比发现,虽然状态模式和策略模式虽然都是行为型设计模式,且类图相似度极高,但是两个策略无论在使用场景、还是对象的职责上,都存在明显的差异,在选用时很容易区分。

参考

https://yiyan.baidu.com/ 文心一言
《设计模式:可复用面向对象软件的基础》 Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides 著 李英军, 马晓星 等译

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1622495.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

2024最新版JavaScript逆向爬虫教程-------基础篇之深入JavaScript运行原理以及内存管理

目录 一、JavaScript运行原理1.1 前端需要掌握的三大技术1.2 为什么要学习JavaScript1.3 浏览器的工作原理1.4 浏览器的内核1.5 浏览器渲染过程1.6 认识JavaScript引擎1.7 V8引擎以及JavaScript的执行过程1.8 V8引擎执行过程 二、JavaScript的执行过程2.1 初始化全局对象2.2 执…

解决宏定义后面无法加分号

总结:注意是针对单行if语句使用,并且宏定义后面必须带分号(格式统一) 参考连接 C语言种do_while(0)的妙用_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV1vk4y1R7VJ/?spm_id_from333.337.search-card.all.click&vd_…

Excel数据处理:动态数据分析报表、单元格数字格式、使用排序工具

1、在生成数据透视表之后选中一个单元格,点击插入,在图表中选择一个自己想要的图表。(生成可视化的图表) 2、在分析中找到切片器,通过点击切片器可以即时变换生成不同的可视化图,可以右键切片器选择关联两个…

matlab 对数坐标画图,及在曲线上加竖直线

matlab 对数坐标画图 方法一:直接对x、y值取对数,然后画图 plot(log(x), log(y), m, LineWidth,1, Marker,.);% ,Color,#EDB120 方法二:将x、y轴刻度改为对数形式 plot(x, y, r, LineWidth,1, Marker,); ax gca();% 获取当前坐标句柄 ax…

解决Oracle锁表的方法

在实际工作中,并发量比较大的项目,经常会出现锁表的问题,下面我将复现这个问题,并给出解决方法。 一、问题复现 1、session1修改aabb表的B字段为迪迦奥特曼,但是不提交该事务。 2、session2也修改这行的这个字段。 发…

【stomp实战】搭建一套websocket推送平台

前面几个小节我们已经学习了stomp协议,了解了stomp客户端的用法,并且搭建了一个小的后台demo,前端页面通过html页面与后端服务建立WebSocket连接。发送消息给后端服务。后端服务将消息内容原样送回。通过这个demo我们学习了前端stomp客户端的…

【leetcode面试经典150题】71. 对称二叉树(C++)

【leetcode面试经典150题】专栏系列将为准备暑期实习生以及秋招的同学们提高在面试时的经典面试算法题的思路和想法。本专栏将以一题多解和精简算法思路为主,题解使用C语言。(若有使用其他语言的同学也可了解题解思路,本质上语法内容一致&…

科技改变视听4K 120HZ高刷新率的投影、电视、电影终有用武之地

早在1888年,法国生理学家埃蒂安朱尔马莱就发明了一套盒式摄像机,能以120帧/s的速度在一条纸膜上曝光照片,但是当时没有相匹配的放映设备。而马莱的另一套拍摄设备是60帧/s的规格,并且图像质量非常好。 受此启发,雷诺的…

Linux上部署Jupyter notebook

安装jupyter notebook pip install notebook #或者 conda install notebook配置 jupyter notebook --generate-config## The IP address the notebook server will listen on. # Default: localhost # 设置可以访问的ip, 默认是localhost, 将其改为 * c.NotebookApp.ip *#…

AutoGPT-Forge使用教程,自行构建agent智能体

本博客给出AutoGPT-forge四个教程的翻译与理解,使用GPT4翻译, 参考官方教程https://aiedge.medium.com/autogpt-forge-a-comprehensive-guide-to-your-first-steps-a1dfdf46e3b4 使用AutoGPT Github代码日期2024/4/22; 博客开始编辑日期20…

java和python刷题的一些语法规则总结(未完成)

语法总结 Java篇1、代码补全2、编程题中常用头文件3、编程题常用的内置方法4、模版 Python篇1、2、编程题中常用的头文件3、编程题中常用的内置方法4、伪代码模版 去哪练习? 1、LeetCode上有个面试模拟 2、牛客公司真题(ACM模式) ⚠️ 笔试均…

Android Gradle查看依赖库

1.gradle :app:dependencies 输出列表展示了所有configuration下的依赖树,依赖关系明显,层次清晰。 2.日志太长可以写入本地文件gradle :app:dependencies > D:/log.txt 3.gradlew processReleaseManifest --stacktrace 跟踪具体报错文件 注…

解决Android studio更换sdk地址后flutter项目显示no device selected

问题描述 因为之前sdk的路径在c盘上,经常在更新或下在sdk后c盘饱满,于是就更换了sdk的路径,更换sdk路径后就导致flutter项目在选择设备的时候出现no device selected 找不到设备,但是在device Manager可以看到物理设备或者是虚拟设备。如下图所示。 问题分析 导致这个问题…

python 报错:ImportError: cannot import name ‘kaiser‘ from ‘scipy.signal‘

python 报错:ImportError: cannot import name kaiser from scipy.signal 介绍第一步:第二步:最终结果: 介绍 这个错误表明在导入 scipy.signal 模块时出现了问题,因为无法找到 kaiser 函数。可能的原因是 scipy 库没有…

C语言 | Leetcode C语言题解之第47题全排列II

题目: 题解: int* vis;void backtrack(int* nums, int numSize, int** ans, int* ansSize, int idx, int* perm) {if (idx numSize) {int* tmp malloc(sizeof(int) * numSize);memcpy(tmp, perm, sizeof(int) * numSize);ans[(*ansSize)] tmp;return…

什么样的汽车制造供应商管理平台 可以既高效又安全?

汽车制造供应商管理是汽车制造商最基础的工作项,因为在汽车制造环节,与供应商间存在着必不可少又高频的业务往来,而在汽车制造供应商之间,文件往来是确保业务顺利进行、沟通协作和质量控制的重要环节。这些文件往来涵盖了多个方面…

linux的“>”和“>>”

在Linux中,>和>>都是用于文件重定向的操作符,它们用于将命令的输出发送到文件中。 > 用于创建一个新文件或覆盖现有文件的内容。当你执行一个如 command > file.txt 的命令时,如果 file.txt 文件存在,它的内容将被…

黄金回收价格和国际金价差多少?

在探讨黄金回收价格与国际金价的关系时,了解黄金的基础知识至关重要。黄金作为一种贵金属,其价值不仅仅在于它本身的物质属性,还包括它的纯度、类型以及市场需求等多种因素。这些特性决定了黄金的价值,并影响着黄金回收价格。 大家…

使用 Gradio 的“热重载”模式快速开发 AI 应用

在这篇文章中,我将展示如何利用 Gradio 的热重载模式快速构建一个功能齐全的 AI 应用。但在进入正题之前,让我们先了解一下什么是重载模式以及 Gradio 为什么要采用自定义的自动重载逻辑。如果你已熟悉 Gradio 并急于开始构建,请直接跳转到第…

LLM 安全 | 大语言模型应用安全入门

一、背景 2023年以来,LLM 变成了相当炙手可热的话题,以 ChatGPT 为代表的 LLM 的出现,让人们看到了无限的可能性。ChatGPT能写作,能翻译,能创作诗歌和故事,甚至能一定程度上做一些高度专业化的工作&#x…