状态模式基础概念

状态模式(State Pattern)是一种行为型设计模式,其核心思想是允许对象在内部状态发生改变时改变它的行为,对象看起来好像修改了它的类。状态模式将状态相关的行为封装在独立的状态类中,并将状态转换逻辑集中管理,从而使对象的行为可以根据状态动态变化,而不必使用大量的条件语句。

状态模式的核心组件

  1. 状态接口(State) - 定义特定状态下的行为接口,所有具体状态类需实现该接口。
  2. 具体状态类(ConcreteState) - 实现状态接口,封装与特定状态相关的行为。
  3. 上下文(Context) - 持有一个状态对象的引用,负责状态的切换和委托行为到当前状态。

状态模式的实现

下面通过一个简单的自动贩卖机示例展示状态模式的实现:

// 1. 状态接口
interface State {void insertCoin();  // 投币void ejectCoin();   // 退币void selectItem();  // 选择商品void dispense();    // 发放商品
}// 2. 具体状态类 - 没有硬币
class NoCoinState implements State {private VendingMachine machine;  // 持有上下文引用public NoCoinState(VendingMachine machine) {this.machine = machine;}@Overridepublic void insertCoin() {System.out.println("您投入了硬币");machine.setState(machine.getHasCoinState());  // 状态转换}@Overridepublic void ejectCoin() {System.out.println("您还没有投币");}@Overridepublic void selectItem() {System.out.println("请先投币");}@Overridepublic void dispense() {System.out.println("请先投币并选择商品");}
}// 3. 具体状态类 - 有硬币
class HasCoinState implements State {private VendingMachine machine;public HasCoinState(VendingMachine machine) {this.machine = machine;}@Overridepublic void insertCoin() {System.out.println("您已经投过硬币了,无需再投");}@Overridepublic void ejectCoin() {System.out.println("硬币已退回");machine.setState(machine.getNoCoinState());  // 状态转换}@Overridepublic void selectItem() {System.out.println("您选择了商品");machine.setState(machine.getSoldState());  // 状态转换}@Overridepublic void dispense() {System.out.println("请先选择商品");}
}// 4. 具体状态类 - 已售出
class SoldState implements State {private VendingMachine machine;public SoldState(VendingMachine machine) {this.machine = machine;}@Overridepublic void insertCoin() {System.out.println("请稍等,正在出货");}@Overridepublic void ejectCoin() {System.out.println("抱歉,您已经选择了商品,无法退币");}@Overridepublic void selectItem() {System.out.println("请稍等,正在出货");}@Overridepublic void dispense() {if (machine.getCount() > 0) {machine.releaseItem();System.out.println("商品已发放");if (machine.getCount() > 0) {machine.setState(machine.getNoCoinState());  // 还有库存,回到无硬币状态} else {System.out.println("商品已售罄");machine.setState(machine.getSoldOutState());  // 库存不足,转为售罄状态}} else {System.out.println("商品已售罄");machine.setState(machine.getSoldOutState());}}
}// 5. 具体状态类 - 售罄
class SoldOutState implements State {private VendingMachine machine;public SoldOutState(VendingMachine machine) {this.machine = machine;}@Overridepublic void insertCoin() {System.out.println("抱歉,商品已售罄");}@Overridepublic void ejectCoin() {System.out.println("您还没有投币");}@Overridepublic void selectItem() {System.out.println("抱歉,商品已售罄");}@Overridepublic void dispense() {System.out.println("抱歉,商品已售罄");}
}// 6. 上下文 - 自动贩卖机
class VendingMachine {private State noCoinState;private State hasCoinState;private State soldState;private State soldOutState;private State state;  // 当前状态private int count;    // 商品数量public VendingMachine(int count) {this.count = count;// 初始化状态noCoinState = new NoCoinState(this);hasCoinState = new HasCoinState(this);soldState = new SoldState(this);soldOutState = new SoldOutState(this);// 设置初始状态if (count > 0) {state = noCoinState;} else {state = soldOutState;}}// 状态转换方法public void setState(State state) {this.state = state;}// 委托行为到当前状态public void insertCoin() {state.insertCoin();}public void ejectCoin() {state.ejectCoin();}public void selectItem() {state.selectItem();}public void dispense() {state.dispense();}// 其他方法public void releaseItem() {if (count > 0) {count--;}}public int getCount() {return count;}// 获取各种状态(供状态类使用)public State getNoCoinState() {return noCoinState;}public State getHasCoinState() {return hasCoinState;}public State getSoldState() {return soldState;}public State getSoldOutState() {return soldOutState;}
}// 7. 客户端代码
public class StatePatternClient {public static void main(String[] args) {// 创建有2个商品的贩卖机VendingMachine machine = new VendingMachine(2);// 测试流程1:投币 -> 选择商品 -> 出货System.out.println("=== 测试流程1 ===");machine.insertCoin();machine.selectItem();machine.dispense();// 测试流程2:投币 -> 退币System.out.println("\n=== 测试流程2 ===");machine.insertCoin();machine.ejectCoin();// 测试流程3:连续购买2个商品,使贩卖机售罄System.out.println("\n=== 测试流程3 ===");machine.insertCoin();machine.selectItem();machine.dispense();machine.insertCoin();machine.selectItem();machine.dispense();// 尝试在售罄状态下操作System.out.println("\n=== 测试售罄状态 ===");machine.insertCoin();machine.selectItem();}
}

状态模式的应用场景

  1. 工作流系统 - 如订单状态(待支付、已支付、已发货、已完成)
  2. 游戏开发 - 角色状态(站立、行走、跑步、跳跃、攻击)
  3. 状态机实现 - 如协议解析、编译原理中的词法分析器
  4. GUI 组件 - 如按钮状态(正常、悬停、点击、禁用)
  5. 线程状态管理 - 线程的不同状态(新建、就绪、运行、阻塞、终止)
  6. 文档编辑系统 - 文档状态(草稿、审核中、已发布、已归档)

状态模式的优缺点

优点

  • 封装状态行为 - 将特定状态的行为封装在独立的类中,提高代码内聚性
  • 简化条件语句 - 避免使用大量的 if-else 或 switch 语句,使代码更清晰
  • 符合开闭原则 - 可以轻松添加新的状态类,无需修改现有代码
  • 状态转换集中管理 - 状态转换逻辑集中在上下文或状态类中,便于维护
  • 状态变化透明 - 状态变化对客户端透明,客户端无需关心状态转换细节

缺点

  • 类数量增加 - 每个状态都需要一个类,可能导致类爆炸
  • 状态间依赖 - 状态类之间可能存在依赖关系,增加系统复杂度
  • 初始化复杂 - 上下文需要初始化所有可能的状态,增加初始化复杂度
  • 不适用于简单状态 - 对于状态较少或状态转换简单的场景,使用状态模式可能过于繁琐

使用状态模式的注意事项

  1. 合理设计状态接口 - 确保状态接口包含所有可能的行为,避免状态类中出现空实现
  2. 控制状态数量 - 避免定义过多的状态,状态过多会增加系统复杂度
  3. 状态转换逻辑 - 决定状态转换逻辑放在上下文还是状态类中:
    • 上下文控制:集中管理状态转换,状态类更简单
    • 状态类控制:状态类可以自主决定何时转换,更灵活
  4. 状态对象的生命周期 - 决定状态对象是单例还是每次创建新实例
  5. 与策略模式的区别 - 状态模式的状态之间通常有关联和转换,而策略模式的策略之间相互独立
  6. 调试和监控 - 状态模式可能使调试变得复杂,建议添加状态日志或监控机制

总结

状态模式通过将对象的状态相关行为封装在独立的状态类中,并将状态转换逻辑集中管理,实现了对象行为的动态变化。它在不修改对象类的前提下,允许对象在内部状态改变时改变其行为,是处理复杂状态转换场景的理想选择。在实际开发中,状态模式常用于工作流系统、游戏开发、状态机实现等领域。合理使用状态模式可以提高系统的可维护性和可扩展性,但需要注意控制类的数量和状态转换逻辑的复杂度。

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

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

相关文章

重学Framework Input模块:如何实现按键一键启动Activity-学员作业

需求背景: 近来vip群里学员朋友有问道一个需求,大概需求就是他们做TV的Framework开发,想要遥控器有一个新定义的儿童节目按键,想要实现这个按键按下后就跳转到儿童节目的Activity。需求拆解及作业要求: 针对上面需求&a…

bmp图像操作:bmp图像保存及raw与bmp转换

1. 保存bmp图像&保存一张正弦图像到D:\1.bmp /********************************************** * fileName bmpinc.h * brief 对bmp文件的操作,包括: * - saveBmp:保存bmp文件 * - Save…

SpringAI——提示词(Prompt)、提示词模板(PromptTemplate)

Prompt 是引导 AI 模型生成特定输出的输入格式,Prompt 的设计和措辞会显著影响模型的响应。最开始Prompt只是单纯的文本文字,后面可以包含占位符,可以识别消息的角色。比如包含占位符的Prompt,也就是我们讲的消息模板(PromptTemplate)&#x…

【深度学习笔记 Ⅰ】5 参数和超参数

在深度学习中,参数(Parameters) 和 超参数(Hyperparameters) 是模型训练中两个核心概念,它们共同决定了模型的性能,但作用方式和优化方法截然不同。以下是详细对比与解析:1. 参数&am…

Linux 阻塞等待框架

在 Linux 设备驱动开发中,阻塞机制 是处理资源暂时不可用(如设备未准备好数据、缓冲区满等)的核心手段。驱动程序可以将被阻塞的进程设置成休眠状态,然后,在资源可用后,再将该进程唤醒。 在 Linux 驱动开发…

PCIe RAS学习专题(3):AER内核处理流程梳理

目录 一、AER内核处理整体流程梳理 二、AER代码重要部分梳理 1、AER初始化阶段 2、中断上半部 aer_irq 3、中断下半部 aer_isr 3.1、aer_isr_one_error 3.2、find_source_device 3.3、aer_process_err_devices 3.4、handle_error_source 3.5、pcie_do_recovery 整体逻…

​HAProxy负载均衡集群概述

前言: 在现代分布式系统中,负载均衡和高可用性是保障服务稳定性和性能的关键技术。HAProxy 作为一款高性能的 TCP/HTTP 负载均衡器,凭借其轻量级、高并发处理能力和灵活的配置机制,成为构建高可用架构的核心组件之一。通过智能的流…

ELN:生物医药科研的数字化引擎——衍因科技引领高效创新

在生物医药研究领域,实验数据的准确记录与管理是科研成败的关键。想象一个场景:某顶尖医学院实验室,研究员小张正为一项抗癌药物实验焦头烂额。纸质记录本中,数据混乱、协作困难,导致实验重复率高达20%。引入衍因科技的…

暑假---作业2

学习目标&#xff1a;xss-1abs 1-8关python美现自动化布尔自注的2、代码进行优化(二分查找)学习内容&#xff1a;1.xss-1abs 1-8关1<h2 align"center">欢迎用户test</h2>2 <script> alert (1)</script&gt<center> <form action&…

【Tensor数据转换】——深度学习.Torch框架

目录 1 Tensor与Numpy 1.1 张量转Numpy 1.2 Numpy转张量 1 Tensor与Numpy 1.1 张量转Numpy 调用numpy()方法可以把Tensor转换为Numpy&#xff0c;此时内存是共享的。 使用copy()方法可以避免内存共享 import torch import numpy as np# tensor转numpy:numpy() def test0…

基于Tranformer的NLP实战(5):BERT实战-基于Pytorch Lightning的文本分类模型

文本分类作为自然语言处理中的基础任务&#xff0c;能够帮助我们将海量医学摘要自动归类到具体疾病领域中。本文将基于NVIDIA NeMo框架&#xff0c;构建一个用于医学疾病摘要分类的深度学习应用&#xff0c;支持将摘要划分为三类&#xff1a;癌症类疾病、神经系统疾病及障碍、以…

14-链路聚合

链路聚合技术 一 链路聚合概述链路聚合定义链路聚合是把多条物理链路聚合在一起&#xff0c;形成一条逻辑链路。应用在交换机、路由器、服务器间链路。分为三层链路聚合和二层链路聚合。二 链路聚合的作用 1. 链路聚合模式静态聚合模式 端口不与对端设备交互信息。选择参考端口…

学习C++、QT---28(QT库中使用QShortcut类对快捷键创建和使用的讲解)

每日一言 所有的努力&#xff0c;都是为了让未来的自己感谢现在的你。 QShortcut 我们的记事本肯定要有通过快捷键对字体的放大和缩小进行控制的功能啊&#xff0c;那么我们这边就这个问题我们需要先学习一下QShortCut 我们这个类就是专门做快捷键的 老样子我们刚开始学习这个…

Web Worker:让前端飞起来的隐形引擎

目录 Web Worker&#xff1a;让前端飞起来的隐形引擎 一、什么是 Web Worker&#xff1f; 1、为什么需要 web worker 2、什么是 web worker 二、基本使用方法 1、创建一个 Worker 文件&#xff08;worker.js&#xff09; 2、主线程引入并使用 三、实战案例&#xff1a;…

关于在VScode中使用git的一些步骤常用命令及其常见问题:

输入 gitee用户 gitee绑定邮箱git config --global user.name "automated-piggy-senior" git config --global user.email "1323280131qq.com"克隆远程库到本地 git clone https://gitee.com/automated-piggy-senior/20250717-test.git常见问题1&#xff1…

LeafletJS 性能优化:处理大数据量地图

引言 LeafletJS 作为一个轻量、灵活的 JavaScript 地图库&#xff0c;以其高效的渲染能力和模块化设计深受开发者喜爱。然而&#xff0c;当处理大数据量&#xff08;如数千个标记、复杂的 GeoJSON 数据或高分辨率瓦片&#xff09;时&#xff0c;LeafletJS 的性能可能面临挑战&…

LLM(Large Language Model)大规模语言模型浅析

参考: https://zhuanlan.zhihu.com/p/7046080918 LLM(Large Language Model)大规模语言模型,是指具有大规模参数和复杂计算结构的机器学习模型。大模型里常说的多少B, B 是 Billion 的缩写&#xff0c;表示 十亿,如DeepSeek满血版 671B(6710亿参数); 大模型本质上是一个使用海量…

【后端】配置SqlSugar ORM框架并添加仓储

目录 1.添加包 2.配置连接字符串 3.配置SqlSugar 3.1.添加基础类 3.2.添加方法 3.2.1.读取配置方法 3.2.2.枚举扩展方法 3.3.添加管理类&#xff08;重要&#xff09; 4.配置仓储 4.1.仓储接口添加 5.注册 6.使用 该文档是配置SqlSugar多租户和加仓储教程。使用 S…

全国高等院校计算机基础教育研究会2025学术年会在西宁成功举办 ——高原论道启新程,数智融合育英才

7 月16日至18日&#xff0c;全国高等院校计算机基础教育研究会2025学术年会在青海西宁隆重召开。大会以“数智融合&#xff0c;创新计算机教育”为主题&#xff0c;汇聚人工智能领域顶尖专家学者、高校校长、产业翘楚及一线教师300 多人&#xff0c;共商人工智能时代计算机基础…

AppTrace:重新定义免填邀请码,解锁用户裂变新高度

​​在移动互联网时代&#xff0c;​用户裂变是App增长的核心引擎&#xff0c;而邀请机制则是裂变的关键驱动力。然而&#xff0c;传统的邀请码机制——依赖用户手动输入、记忆复杂字符——已经成为用户体验的绊脚石&#xff0c;导致转化率下降、运营成本上升。​AppTrace​ 作…