技术成神之路:设计模式(七)状态模式

1.介绍


状态模式(State Pattern)是一种行为设计模式,它允许一个对象在其内部状态改变时改变其行为。这个模式将状态的相关行为封装在独立的状态类中,并将不同状态之间的转换逻辑分离开来。

2.主要作用


状态模式的主要作用是让一个对象在其内部状态改变时,其行为也随之改变,但同时又使得状态的变化对外部来说是透明的。它将状态转移的逻辑封装在状态类中,使得增加新的状态变得简单,同时避免状态间的相互依赖,使得代码更加清晰。

3.解决的问题


状态模式主要解决的问题是对象在不同状态下的行为变化问题,以及状态转换的复杂性管理。

状态模式可以帮助解决以下几类问题:

  1. 消除大量的条件判断语句:
    我们在项目中会经常用到条件判断语句,而有的对象行为会使用到大量的条件语句(如if-else或switch-case)来实现。在某些情况下条件语句少了还好,多了就是灾难,既不美观,又不优雅,唯一好处就是方便使用,但维护起来不方便,如果不使用状态模式,可能需要在每个操作的实现中加入大量的状态判断,这会导致代码复杂、难以维护和扩展。

  2. 状态转换的管理:
    对象的状态不仅仅影响其行为,还涉及到状态之间的转换逻辑。就算你为了方便使用了 if-else或switch-case ,那么处理转换逻辑的代码要写在哪里,状态模式通过将每种状态封装为一个独立的类,使得状态转换的逻辑局部化,每个状态类负责自己的状态判断和转换条件,从而简化了整体的状态管理。

  3. 提高代码的可读性和可维护性:
    这个没什么好说的,设计模式通用✨

4.模式原理


包含角色:

  1. Context(环境类):定义客户感兴趣的接口,并维护一个具体状态子类的实例,这个实例定义当前状态。
  2. State(状态接口/抽象类):定义一个接口或抽象类,封装与Context的一个特定状态相关的行为。
  3. ConcreteState(具体状态类):每一个具体状态类实现了在状态接口中定义的行为,负责状态转换时的逻辑。

了解策略模式的烙铁看到这里是不是很熟悉,包含的角色几乎一模一样,只是把策略两个字改成了状态,那么状态模式是不是就不用继续往下看了?no no no,它们还是有差别滴…

UML类图:
在这里插入图片描述
代码示例:

// State 接口
interface DocumentState {void edit(Document doc);void save(Document doc);void print(Document doc);
}// ConcreteState 具体状态类
class EditableState implements DocumentState {public void edit(Document doc) {// 编辑操作}public void save(Document doc) {// 保存操作}public void print(Document doc) {// 打印操作}
}// Context 环境类
class Document {private DocumentState currentState;public Document() {this.currentState = new EditableState(); }public void changeState(DocumentState newState) {this.currentState = newState;}public void edit() {currentState.edit(this);}public void save() {currentState.save(this);}public void print() {currentState.print(this);}
}// 使用
Document document = new Document();
document.edit();  
document.save();  
document.print(); 
document.changeState(new ReadOnlyState());
document.edit();  // 无法编辑,状态切换到只读

不知道看到这里,你再回想起策略模式时,是不是还有点迷糊,现在分不清没关系,继续往下看,加深一下印象

状态模式和策略模式区别总结:

  1. 关注点不同:
  • 状态模式关注对象在不同状态下的行为差异,封装了不同状态的行为。
  • 策略模式关注的是算法的不同实现方式,允许算法在不影响客户端的情况下独立变化。
  1. 使用场景不同:
  • 状态模式适用于对象的行为在状态改变时发生改变的情况,状态之间有明显的转换关系。
  • 策略模式适用于客户端需要在多个算法中选择一种时,并且允许在运行时切换算法。
  1. 关系不同:
  • 状态模式中,状态之间存在特定的状态转换关系,通常由Context类来维护和切换状态。
  • 策略模式中,各个策略(算法)之间通常是相互独立的,客户端通过选择不同的策略对象来实现不同的行为。

是不是突然觉得差别还是挺大的嘛,思路一下就清晰了,其实不用理解那么深入,它们的名字就是最大的差异点,通过名字你可以一点一点联想它们的实现方式,这样你就真正理解了设计模式的精髓。

5.优缺点


优点

  • 清晰的状态转换:状态模式将状态和行为封装在独立的类中,使状态转换更加清晰。
  • 提高可维护性和扩展性:通过分离状态和行为,代码更加模块化,便于添加新状态和修改现有状态。
  • 减少条件分支:避免了在上下文类中使用大量的条件分支(if-else 或 switch-case)。

缺点

  • 增加类的数量:每个状态都需要一个类,可能会导致系统中类的数量增加,从而增加维护难度(设计模式通病)。
  • 状态之间的依赖:某些状态可能依赖于其他状态,导致状态类之间的耦合(此条可忽略)。

6.应用场景


状态模式 状态模式 首先你得有不同状态才行,举几个简单场景:

  • 对象行为依赖于其状态:如电灯开关、文档编辑器的状态(如草稿、审核中、已发布等)。
  • 状态转换复杂:状态之间存在复杂的转换逻辑,需要清晰地管理状态和行为。
  • 需要频繁更改状态或扩展新状态:如游戏角色的状态、工作流引擎的状态等。

7.总结


状态模式通过将状态和状态相关的行为封装在独立的类中,使得状态转换逻辑更加清晰和可维护。它提高了代码的扩展性和可维护性,适用于对象行为依赖于状态且状态转换复杂的场景。然而,需要注意的是,状态模式可能会增加系统中类的数量,使得系统的维护变得更加复杂。在使用状态模式时,需要权衡其带来的好处和潜在的复杂性。

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

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

相关文章

数据结构—链式二叉树-C语言

代码位置:test-c-2024: 对C语言习题代码的练习 (gitee.com) 一、前言: 在现实中搜索二叉树为常用的二叉树之一,今天我们就要通过链表来实现搜索二叉树。实现的操作有:建二叉树、前序遍历、中序遍历、后序遍历、求树的节点个数、求…

MySQL日期和时间相关函数

目录 1. 获取当前时间和日期 2. 获取当前日期 3. 获取当前时间 4. 获取单独的年/月/日/时/分/秒 5. 添加时间间隔 date_add ( ) 6. 格式化日期 date_format ( ) 7. 字符串转日期 str_to_date () 8. 第几天 dayofxx 9. 当月最后一天 last_day ( ) 10. 日期差 datedif…

H. Beppa and SwerChat【双指针】

思路分析&#xff1a;运用双指针从后往前扫一遍&#xff0c;两次分别记作数组a&#xff0c;b&#xff0c;分别使用双指针i和j来扫&#xff0c;如果一样就往前&#xff0c;如果不一样&#xff0c;i–,ans #include<iostream> #include<cstring> #include<string…

SQL server 练习题2

课后作业 作业 1&#xff1a;自己查找方法&#xff0c;将 homework_1.xls 文件数据导入到 SQLServer 的 homework 数据库中。数据导入完成后&#xff0c;把表名统一改为&#xff1a;外卖表 如下所示&#xff1a; 作业 2&#xff1a;找出所有在 2020 年 5 月 1 日至 5 月 31 …

Zookeeper之CAP理论及分布式一致性算法

CAP理论 CAP理论告诉我们&#xff0c;一个分布式系统不可能同时满足以下三种 一致性&#xff08;C:consistency&#xff09;可用性&#xff08;A:Available&#xff09;分区容错性&#xff08;P:Partition Tolerance&#xff09; 这三个基本要求&#xff0c;最多只能同时满足…

部署k8s 1.28.9版本

继上篇通过vagrant与virtualBox实现虚拟机的安装。笔者已经将原有的vmware版本的虚拟机卸载掉了。这个场景下&#xff0c;需要重新安装k8s 相关组件。由于之前写的一篇文章本身也没有截图。只有命令。所以趁着现在。写一篇&#xff0c;完整版带截图的步骤。现在行业这么卷。离…

SpringBoot中常用的注解及其用法

1. 常用类注解 RestController和Controller是Spring中用于定义控制器的两个类注解. 1.1 RestController RestController是一个组合类注解,是Controller和ResponseBody两个注解的组合,在使 用 RestController 注解标记的类中&#xff0c;每个方法的返回值都会以 JSON 或 XML…

【Android安全】Ubuntu 下载、编译 、刷入Android-8.1.0_r1

0. 环境准备 Ubuntu 16.04 LTS&#xff08;预留至少95GB磁盘空间&#xff0c;实测占94.2GB&#xff09; Pixel 2 XL 要买欧版的&#xff0c;不要美版的。 欧版能解锁BootLoader、能刷机。 美版IMEI里一般带“v”或者"version"&#xff0c;这样不能解锁BootLoader、…

394. 字符串解码 739. 每日温度(LeetCode热题100)

394. 字符串解码 - 力扣&#xff08;LeetCode&#xff09; curr_str&#xff1a;遍历整个字符串时 如果左边有[&#xff0c;且无相应右括号和其匹配&#xff0c;那么curr_str就表示该[到当前位置的解码字符串如果左边的[]已经匹配&#xff0c;或者没有[]&#xff0c;curr_siz…

找不到vcruntime140_1.dll 无法执行的相关解决方法,如何高效率修复vcruntime140_1.dll

当出现“找不到 vcruntime140_1.dll 无法执行”这类提示时&#xff0c;意味着你的系统中的 vcruntime140_1.dll 文件已经缺失或者损坏。为了恢复并正常启动你的程序&#xff0c;你需要对这个 DLL 文件进行修复。接下来&#xff0c;我们将详细介绍如何进行这一操作。 一.找不到v…

数学建模·层次分析法

层次分析法 LAF 定义 评价体系的优劣影响&#xff0c;计算评价指标的权重的一种方法 主观性较强&#xff0c;现在一般不用 主要步骤 关键在于一致性检验和求权值 权重的计算 注意权重之和为1&#xff0c;需要归一化 算数平均法 特征值法 矩阵的一致性检验 为什么要检验…

sentinel网关限流配置及使用

sentinel控制台源码&#xff1a;https://download.csdn.net/download/yixin605691235/89543923 sentinel控制台jar包&#xff1a;https://download.csdn.net/download/yixin605691235/89543931 不同环境直接修改jar包中的application.yml文件中的nacos地址就可以了。 一、网关限…

大数据信用查询有哪些问题值得注意呢?

随着大数据技术的不断发展&#xff0c;大数据信用报告成为一种新型的信用风险检测工具&#xff0c;被很多的银行和机构广泛用于信用风险评估&#xff0c;那大数据信用查询有哪些问题值得注意呢?本文就带大家一起去了解一下&#xff0c;希望对你有一定的帮助。 大数据信用查询这…

python 方向梯度直方图(HOG)算法 【附两种实现方法并可视化】

目录 一、概述1.1 算法定义1.2 实现过程二、方法1(skimage库)2.1 代码实现2.2 结果示例三、方法2(cv2库)3.1 代码实现3.2 结果示例四、结果对比🙋 结果预览 一、概述 1.1 算法定义 方向梯度直方图(Histogram of Oriented Gradient,HOG):是应用在计算机视觉和图像处…

LLM微调

文章目录 一. 常见微调分类1.1 全量微调&#xff08;FFT&#xff1a;Full Fine-tuning&#xff09;1.2 参数高效微调(PEFT&#xff1a;Parameter-Efficient Fine-Tuning)1.3 指令微调&#xff08;IFT&#xff1a;Instructional Fine-tuning&#xff09;1.3.1 Hard prompt1.3.2 …

Docker存储目录问题,如何修改Docker默认存储位置?(Docker存储路径、Docker存储空间)etc/docker/daemon.json

文章目录 如何更改docker默认存储路径&#xff1f;版本1&#xff08;没测试&#xff09;版本2&#xff08;可行&#xff09;1. 停止 Docker 服务&#xff1a;2. 创建新的存储目录&#xff1a;3. 修改 Docker 配置文件&#xff1a;4. 移动现有的 Docker 数据&#xff1a;5. 重新…

Uniapp自定义动态加载组件(2024.7更新)

1.本次介绍如何使用uniapp实现自定义动态加载Loading的组件&#xff0c;可以gif格式&#xff0c;也可以mp4格式等; 编写自定义Loading组件(CustomLoader.vue)&#xff1b;组件中含有“动态接收图片路径”&#xff0c;“10秒超时未false则自动断开关闭Loading”&#xff1b;在全…

【JavaScript 算法】广度优先搜索:层层推进的搜索策略

&#x1f525; 个人主页&#xff1a;空白诗 文章目录 一、算法原理二、算法实现三、应用场景四、优化与扩展五、总结 广度优先搜索&#xff08;Breadth-First Search, BFS&#xff09;是一种用于遍历或搜索图或树数据结构的算法。该算法从起始节点开始&#xff0c;逐层向外扩展…

小程序-2(WXML数据模板+WXSS模板样式+网络数据请求)

目录 1.WXML数据模板 数据绑定 事件绑定 小程序中常用的事件 事件对象的属性列表 target和currentTarget的区别 bindtap的语法格式 在事件处理事件中为data中的数据赋值 事件传参与数据同步 事件传参 bindinput的语法绑定事件 文本框和data的数据同步 条件渲染 w…

SpringCloud | 单体商城项目拆分(微服务)

为什么要进行微服务拆分&#xff1f; 在平常的商城项目中&#xff0c;我们一般的项目结构模块都是将各种业务放在同一个项目文件夹&#xff0c;比如像&#xff1a; 用户&#xff0c;购物车&#xff0c;商品&#xff0c;订单&#xff0c;支付等业务都是放在一起&#xff0c;这样…