在软件开发中,我们经常会遇到对象的行为随着其内部状态的变化而变化的情况。例如,一个订单可能处于"待支付"、"已支付"、"已发货"或"已完成"等不同状态,每个状态下订单的操作逻辑可能完全不同。如果直接在代码中使用大量的if-elseswitch-case语句来判断状态,会导致代码臃肿、难以维护,并且违反开闭原则(OCP)

状态模式(State Pattern)提供了一种优雅的解决方案,它允许对象在运行时根据内部状态改变其行为,而不必在代码中显式地检查状态。本文将深入探讨状态模式的核心概念、实现方式、优缺点以及实际应用场景,并通过代码示例帮助读者更好地理解该模式。

1. 什么是状态模式?

1.1 定义

状态模式是一种行为型设计模式,它允许一个对象在其内部状态改变时改变其行为,使得对象看起来像是修改了它的类。

1.2 核心思想

  • 将状态抽象成独立的类,每个状态类负责处理该状态下的行为。

  • 上下文(Context)对象持有一个状态对象的引用,并将行为委托给当前状态对象。

  • 状态转换由状态类自身或上下文类控制,而不是在业务逻辑中硬编码。

1.3 适用场景

  • 对象的行为依赖于它的状态,并且需要在运行时动态改变行为。

  • 代码中包含大量与对象状态相关的条件分支语句,导致逻辑复杂。

  • 状态转换逻辑较复杂,且未来可能新增状态。

2. 状态模式的结构

状态模式主要由以下几个角色组成:

角色作用
Context(上下文)定义客户端接口,维护当前状态对象。
State(抽象状态)定义状态接口,封装与特定状态相关的行为。
ConcreteState(具体状态)实现状态接口,处理该状态下的行为逻辑,并可触发状态转换。

2.1 UML 类图

┌─────────────┐       ┌─────────────┐
│   Context   │       │    State    │
├─────────────┤       ├─────────────┤
│ -state:State│<>---->│ +handle()   │
├─────────────┤       └─────────────┘
│ +request()  │               ▲
└─────────────┘               ││┌──────────────┴──────────────┐│                             │┌─────────────┐               ┌─────────────┐│ConcreteStateA│               │ConcreteStateB│├─────────────┤               ├─────────────┤│ +handle()   │               │ +handle()   │└─────────────┘               └─────────────┘

3. 代码示例:订单状态管理

假设我们有一个订单系统,订单可能处于以下状态:

  • 待支付(Pending)

  • 已支付(Paid)

  • 已发货(Shipped)

  • 已完成(Completed)

3.1 定义状态接口

public interface OrderState {void next(Order order);void prev(Order order);void printStatus();
}

3.2 实现具体状态类

// 待支付状态
public class Pending implements OrderState {@Overridepublic void next(Order order) {order.setState(new Paid());}@Overridepublic void prev(Order order) {System.out.println("订单尚未支付,无法回退。");}@Overridepublic void printStatus() {System.out.println("订单状态:待支付");}
}// 已支付状态
public class Paid implements OrderState {@Overridepublic void next(Order order) {order.setState(new Shipped());}@Overridepublic void prev(Order order) {order.setState(new Pending());}@Overridepublic void printStatus() {System.out.println("订单状态:已支付");}
}// 已发货状态
public class Shipped implements OrderState {@Overridepublic void next(Order order) {order.setState(new Completed());}@Overridepublic void prev(Order order) {order.setState(new Paid());}@Overridepublic void printStatus() {System.out.println("订单状态:已发货");}
}// 已完成状态
public class Completed implements OrderState {@Overridepublic void next(Order order) {System.out.println("订单已完成,无法继续推进。");}@Overridepublic void prev(Order order) {order.setState(new Shipped());}@Overridepublic void printStatus() {System.out.println("订单状态:已完成");}
}

3.3 定义上下文类(Order)

public class Order {private OrderState state;public Order() {this.state = new Pending(); // 初始状态:待支付}public void setState(OrderState state) {this.state = state;}public void nextState() {state.next(this);}public void prevState() {state.prev(this);}public void printStatus() {state.printStatus();}
}

3.4 客户端测试

public class Client {public static void main(String[] args) {Order order = new Order();order.printStatus(); // 待支付order.nextState();   // 推进到已支付order.printStatus(); // 已支付order.nextState();   // 推进到已发货order.printStatus(); // 已发货order.prevState();   // 回退到已支付order.printStatus(); // 已支付order.nextState();   // 推进到已发货order.nextState();   // 推进到已完成order.printStatus(); // 已完成}
}

输出结果:

订单状态:待支付
订单状态:已支付
订单状态:已发货
订单状态:已支付
订单状态:已发货
订单状态:已完成

4. 状态模式的优缺点

4.1 优点

✅ 符合单一职责原则:每个状态类只负责自己的行为逻辑。
✅ 符合开闭原则(OCP):新增状态时无需修改现有代码。
✅ 减少条件分支:避免复杂的if-elseswitch-case逻辑。
✅ 状态转换逻辑清晰:状态转换由状态类自身控制,易于维护。

4.2 缺点

❌ 类数量增加:每个状态都需要一个单独的类,可能导致类膨胀。
❌ 状态转换逻辑分散:如果状态转换逻辑复杂,可能难以追踪。
❌ 可能引入循环依赖:状态类可能依赖上下文类,反之亦然。

5. 状态模式的实际应用

5.1 电商订单系统

  • 订单状态流转:待支付 → 已支付 → 已发货 → 已完成

  • 不同状态下,订单的操作(如取消、退款)逻辑不同。

5.2 游戏角色状态

  • 角色可能有站立奔跑跳跃攻击等状态。

  • 不同状态下,角色的动画、移动速度、碰撞检测等行为不同。

5.3 线程状态管理

  • Java 线程的状态:NEWRUNNABLEBLOCKEDWAITINGTERMINATED

  • 不同状态下,线程的调度策略不同。

5.4 UI 组件状态

  • 按钮的状态:正常悬停按下禁用

  • 不同状态下,按钮的样式和交互逻辑不同。

6. 状态模式 vs. 策略模式

状态模式和策略模式在结构上非常相似,但它们的设计意图不同

对比点状态模式策略模式
目的让对象在不同状态下改变行为让客户端选择不同的算法
状态转换状态类可以自动切换策略通常由客户端设置
依赖关系状态类可能依赖上下文策略类通常独立

7. 总结

状态模式是一种强大的设计模式,特别适用于对象行为随状态变化而变化的场景。它通过将状态逻辑分散到不同的类中,使得代码更加清晰、可扩展。尽管它可能增加类的数量,但在复杂状态管理场景下,它能显著提升代码的可维护性。

适用场景总结:

  • 对象有多个状态,且行为随状态变化。

  • 代码中有大量状态相关的条件分支。

  • 未来可能新增状态,需要灵活扩展。

推荐使用场景:
✅ 订单状态管理
✅ 游戏角色状态切换
✅ 线程/进程状态管理
✅ UI 组件交互状态

 

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

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

相关文章

企业级网络综合集成实践:VLAN、Trunk、STP、路由协议(OSPF/RIP)、PPP、服务管理(TELNET/FTP)与安全(ACL)

NE综合实验4 一、实验拓扑二、实验需求 按照图示配置IP地址。Sw7和sw8之间的直连链路配置链路聚合。公司内部业务网段为vlan10和vlan20&#xff0c;vlan10是市场部&#xff0c;vlan20是技术部&#xff0c;要求对vlan进行命名以便区分识别&#xff1b;pc10属于vlan10&#xff0c…

小架构step系列20:请求和响应的扩展点

1 概述通过上一篇了解请求和响应的流程&#xff0c;Spring在设计上留了不少扩展点。里面通过查找接口的方式获取的地方&#xff0c;都可以成为一种扩展点&#xff0c;因为只要实现这类接口就可以成为Spring加载的一部分。本文了解一下这些扩展点&#xff0c;方便后面进行扩展。…

模型材质一键替换~轻松还原多种三维场景

1. 概述模型的材质决定了三维场景的整体视效&#xff0c;山海鲸可视化不仅支持模型材质的替换与编辑&#xff0c;而且提供了大量现成的模型材质供大家使用&#xff0c;能够帮助大家实现更高效的三维场景搭建。模型材质主要分为PBR材质和水面材质两个部分。其中大部分静态模型都…

【JS逆向基础】数据库之mysql

前言&#xff1a;mysql数据库管理系统&#xff0c;由瑞典MySQL AB 公司开发&#xff0c;目前属于 Oracle 旗下公司。MySQL 最流行的关MySQL是一个开源免费的关系型数据库管系型数据库管理系统&#xff0c;在 WEB 应用方面ySQL是最好的 RDBMS (Relational Database Management S…

金融工程、金融与经济学知识点

本文整理了20个金融工程、金融和经济学知识点及逻辑&#xff0c;这些是理解金融市场运作和进行量化分析的基石。 1. 金融工程 - 远期与期权&#xff08;Forward & Option&#xff09;的定价与风险管理 远期定价&#xff1a; 利用无套利原则&#xff0c;远期合约的价格应等…

Vue 3 中导出 Excel 文件

在 Vue 3 中导出 Excel 文件&#xff0c;通常可以使用一些流行的 JavaScript 库&#xff0c;如 SheetJS (xlsx) 或者 exceljs。这里我将分别介绍如何使用这两个库来在 Vue 3 应用中导出 Excel 文件。方法 1&#xff1a;使用 SheetJS (xlsx)安装 SheetJS首先&#xff0c;你需要安…

奇麟大数据:前端大文件上传解决方案

在奇麟大数据业务系统的开发及使用过程中&#xff0c;例如OBS对象存储文件管理、流计算DSC依赖管理&#xff0c;经常会遇到上传文件这样的基础需求&#xff0c;一般情况下&#xff0c;前端上传文件就是new FormData&#xff0c;然后把文件 append 进去&#xff0c;然后post发送…

立创EDA中双层PCB叠层分析

立创EDA中双层PCB叠层分析 结论&#xff1a;立创EDA中的双层 PCB 叠层视图相比传统视图&#xff0c;多出一个焊盘层&#xff08;博主命名&#xff09;&#xff1b; 1. 传统双层 PCB 叠层示意图 丝印层 印刷元件标识、极性标记及厂商信息 辅助组装与后期维护 阻焊层 覆盖铜层表…

深入理解进程:从底层原理到硬件系统实战

深入理解进程&#xff1a;从底层原理到嵌入式实战&#xff08;3-4 万字详解&#xff09; 前言&#xff1a;为什么硬件开发者必须吃透进程&#xff1f; 作为嵌入式开发者&#xff0c;你可能会说&#xff1a;“我平时用的 RTOS 里只有任务&#xff08;Task&#xff09;&#xff0…

Elasticsearch 简化指南:GCP Google Compute Engine

作者&#xff1a;来自 Elastic Eduard Martin 系列内容的一部分&#xff1a;开始使用 Elasticsearch&#xff1a;GCP 想获得 Elastic 认证&#xff1f;看看下一期 Elasticsearch Engineer 培训什么时候开始&#xff01; Elasticsearch 拥有丰富的新功能&#xff0c;帮助你根据…

STM32的定时器输入捕获-超声波测距案例

STM32的定时器输入捕获-超声波测距案例 gitee代码输入捕获硬件电路案例说明主函数代码 gitee代码 https://gitee.com/xiaolixi/l-stm32/tree/master/STM32F103C8T6/2-1tem-ld-timer-input-pluse 输入捕获硬件电路 超声波测距案例说明 使用超声波测距传感器使用tim1的输入捕获…

[特殊字符] Spring Boot 常用注解全解析:20 个高频注解 + 使用场景实例

一文掌握 Spring Boot 中最常用的 20 个注解&#xff0c;涵盖开发、配置、Web、数据库、测试等场景&#xff0c;配合示例讲解&#xff0c;一站式掌握&#xff01;&#x1f4cc; 一、核心配置类注解 1. SpringBootApplication 作用&#xff1a;标记为 Spring Boot 应用的入口类&…

【工具变量】地级市城市包容性绿色增长数据(2011-2023年)

城市包容性绿色增长是指在推动城市经济增长的过程中&#xff0c;兼顾环境可持续性、社会公平和包容性发展的理念与实践。它强调在实现绿色转型和低碳发展的同时&#xff0c;保障社会各群体&#xff0c;特别是弱势群体的利益与参与权利&#xff0c;确保增长成果能够公平共享 本…

深入理解React Hooks:从使用到原理

4. 源码解析类:《深入理解React Hooks:从使用到原理》 # 深入理解React Hooks:从使用到原理🔥 **背景**: - Hooks解决了Class组件的哪些问题? - 为什么不能在循环/条件中调用Hooks?🔍 **核心原理**:### 1. Hooks链表 React内部维护一个单向链表:fiber.memoizedSta…

【云原生】Docker 部署 Elasticsearch 9 操作详解

目录 一、前言 二、Elasticsearch 9 新特性介绍 2.1 基于 Lucene 10 重大升级 2.2 Better Binary Quantization(BBQ) 2.3 Elastic Distributions of OpenTelemetry(EDOT) 2.4 LLM 可观测性 2.5 攻击发现与自动导入 2.6 ES|QL 增强 2.7 语义检索 三、基于Docker部署…

uview-ui使用u-search搜索框

1、效果图 2、带地址搜索框&#xff0c;在微信小程序线上需要开启地图定位接口&#xff0c;若没有权限则显示不了城市名&#xff0c;注意事项参考uniapp相关地图 API调用-CSDN博客 <template><view><u-sticky offset-top"-1"><u-search v-mode…

Elasticsearch+Logstash+Kibana部署

目录 一、实验准备 1.下载安装 2.下载java 2.同步主机系统时间 二、部署 1.部署elasticsearch 修改 /etc/elasticsearch/elasticsearch.yml 配置文件 修改 /etc/hosts/ 文件 启动elasticsearch 查看是否启动进程netstat -antptu | grep java 2.部署logstash 进入/et…

TEngine学习

关于静态类中的静态变量赋值&#xff1a; public static class ActorEventDefine{public static readonly int ScoreChange RuntimeId.ToRuntimeId("ActorEventDefine.ScoreChange");public static readonly int GameOver RuntimeId.ToRuntimeId("ActorEventD…

猎板:在 5G 与 AI 时代,印制线路板如何满足高性能需求

5G 与 AI 技术的深度融合&#xff0c;推动电子设备向高速传输、高算力、高集成方向发展&#xff0c;印制线路板&#xff08;PCB&#xff09;作为核心载体&#xff0c;其性能直接决定终端设备的运行效率与可靠性。猎板 PCB 聚焦 5G 通信的高频需求与 AI 算力的密集需求&#xff…

教你如何借助AI精读文献

目录1. 原文2. 对文献有一个快速的理解3. 专业术语解读4. 解答疑问5. 借助AI翻译摘要和引言部分5.1 **摘要 (Abstract)**5.2 **引言 (Introduction)**6. 介绍论文中的“Stack-Propagation”7. 查阅论文里的参考文献&#xff0c;看看他是如何在Introduction中引述研究进展文献&a…