设计模式之状态模式:优雅管理对象行为变化

引言

状态模式(State Pattern)是一种行为型设计模式,它允许对象在其内部状态改变时改变它的行为,使对象看起来似乎修改了它的类。状态模式将状态转移逻辑和状态相关行为封装在独立的状态类中,完美解决了复杂条件判断问题。本文将深入解析状态模式的核心思想、实现方式及典型应用场景。


1. 状态模式的核心概念

1.1 什么是状态模式?

状态模式通过以下三个角色管理状态转换:

  • Context(上下文):维护当前状态实例

  • State(抽象状态):定义状态接口

  • ConcreteState(具体状态):实现特定状态行为

1.2 典型应用场景
  • 订单状态流转(待支付、已发货、已完成等)

  • 游戏角色状态(站立、奔跑、跳跃等)

  • 工作流引擎

  • UI控件状态管理(禁用/启用、活跃/非活跃)


2. 状态模式的实现方式

2.1 基础实现模板
// 状态接口
interface State {void handle(Context context);
}// 具体状态A
class ConcreteStateA implements State {@Overridepublic void handle(Context context) {System.out.println("处理状态A的行为");context.setState(new ConcreteStateB()); // 状态转移}
}// 具体状态B
class ConcreteStateB implements State {@Overridepublic void handle(Context context) {System.out.println("处理状态B的行为");context.setState(new ConcreteStateA()); // 状态转移}
}// 上下文
class Context {private State currentState;public Context(State initialState) {this.currentState = initialState;}public void setState(State state) {this.currentState = state;}public void request() {currentState.handle(this); // 委托给当前状态}
}// 使用示例
public class Client {public static void main(String[] args) {Context context = new Context(new ConcreteStateA());context.request(); // 输出A行为,切换到Bcontext.request(); // 输出B行为,切换回A}
}
2.2 进阶实现技巧
  1. 状态共享:无内部状态的具体状态可设计为单例

  2. 状态创建管理:使用工厂方法管理状态实例

  3. 状态转移表:用Map维护状态转移规则


3. 状态模式的最佳实践

3.1 与策略模式的区别
  • 状态模式:状态间知晓彼此,自动触发状态转移

  • 策略模式:策略相互独立,由客户端指定策略

3.2 性能优化
  • 状态对象复用:对无状态的状态对象使用享元模式

  • 延迟初始化:按需创建状态对象

3.3 设计原则
  • 开闭原则:新增状态无需修改现有代码

  • 单一职责:每个状态类只关注特定状态行为


4. 状态模式的实际应用

4.1 电商订单系统
// 订单状态接口
interface OrderState {void confirm(OrderContext context);void cancel(OrderContext context);void ship(OrderContext context);
}// 具体状态:待支付
class UnpaidState implements OrderState {@Overridepublic void confirm(OrderContext context) {System.out.println("订单支付成功");context.setState(new PaidState());}@Overridepublic void cancel(OrderContext context) {System.out.println("订单已取消");context.setState(new CancelledState());}@Overridepublic void ship(OrderContext context) {System.out.println("订单未支付不能发货");}
}// 上下文类
class OrderContext {private OrderState currentState;public OrderContext() {this.currentState = new UnpaidState(); // 初始状态}// 委托方法...
}// 使用示例
OrderContext order = new OrderContext();
order.confirm(); // 支付成功,状态转为PaidState
4.2 交通信号灯系统
// 状态接口
interface TrafficLightState {void change(TrafficLight light);String getColor();
}// 具体状态
class RedLight implements TrafficLightState {@Overridepublic void change(TrafficLight light) {light.setState(new GreenLight());}@Overridepublic String getColor() {return "红色";}
}// 上下文类
class TrafficLight {private TrafficLightState state;public void change() {state.change(this);}public void show() {System.out.println("当前信号灯:" + state.getColor());}
}
4.3 播放器状态控制
// 播放器状态接口
interface PlayerState {void play(MediaPlayer player);void pause(MediaPlayer player);void stop(MediaPlayer player);
}// 具体状态:播放中
class PlayingState implements PlayerState {@Overridepublic void play(MediaPlayer player) {System.out.println("已在播放状态");}@Overridepublic void pause(MediaPlayer player) {System.out.println("暂停播放");player.setState(new PausedState());}@Overridepublic void stop(MediaPlayer player) {System.out.println("停止播放");player.setState(new StoppedState());}
}// 上下文类
class MediaPlayer {private PlayerState state;public void play() {state.play(this);}public void changeState(PlayerState newState) {this.state = newState;}
}

5. 状态模式的优缺点分析

5.1 优势
  • 消除条件分支:用多态代替复杂的状态判断

  • 易于扩展:新增状态只需添加新类

  • 集中状态逻辑:每个状态的行为局部化

5.2 局限性
  • 类数量增加:每个状态对应一个类

  • 状态转换不直观:转移逻辑分散在各状态类中

  • 不适合简单状态机:简单场景可能过度设计


结语

状态模式是管理复杂状态转换的利器,特别适合行为随状态改变而显著变化的场景。通过将每种状态封装为独立类,代码变得清晰可维护。在实际应用中,可以结合备忘录模式实现状态历史记录,或与观察者模式实现状态变更通知,构建更强大的系统架构。

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

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

相关文章

【算法】归并排序

算法系列七:归并排序 一、归并排序的递归探寻 1.思路 2.搭建 2.1设计过掉不符情况(在最底层时) 2.2查验能实现基础排序(在最底层往上点时) 2.3跳转结果继续往上回搭 3.实质 4.实现 二、递归的调用栈 1.递归的…

线束线缆从二维设计到虚拟验证全流程解决方案

一、传统设计中的痛点 线缆的开发设计是横跨多专业多学科的庞大工程,通常会划分为几大阶段逐次推进,由于每个阶段的工作任务不同,所以在不同设计阶段使用的工具也完全不同,由此导致整个设计流程中工程师常常要跨平台协作&#xf…

【智驾中的大模型 -1】自动驾驶场景中的大模型

1. 前言 我们知道,大模型现在很火爆,尤其是 deepseek 风靡全球后,大模型毫无疑问成为为中国新质生产力的代表。百度创始人李彦宏也说:“2025 年可能会成为 AI 智能体爆发的元年”。 随着科技的飞速发展,大模型的影响…

个人博客系统后端 - 注册登录功能实现指南

一、功能概述 个人博客系统的注册登录功能包括: 用户注册:新用户可以通过提供用户名、密码、邮箱等信息创建账号用户登录:已注册用户可以通过用户名和密码进行身份验证,获取JWT令牌身份验证:使用JWT令牌访问需要认证…

投行交易与风控系统的消费侧幂等架构设计与实战

1.背景和痛点 1.1 资金操作敏感性场景 核心需求: 交易唯一性:资金类操作必须保证全局唯一执行计算原子性:风控指标计算需具备事务性特征审计追溯:所有操作需保留完整幂等轨迹 1.2 业务损失统计 二、技术挑战与架构设计 2.1 分…

odoo-046 视图显示的 name 数据库中存储的不一样

文章目录 一、问题由来二、排查经过1. 问 deepseek2. 验证3. 新问题 三、 总结四、补充(翻译模型 ir.translation 中 src 和 value 字段详解) 一、问题由来 客户有多个公司,使用多个数据库。他们有时需要同步不同数据库之间的数据的需求。在…

充电宝项目:规则引擎Drools学习

文章目录 规则引擎 Drools1 问题2 规则引擎概述2.1 规则引擎2.2 使用规则引擎的优势2.3 规则引擎应用场景2.4 Drools介绍 3 Drools入门案例3.1 创建springboot项目 引入依赖3.2 添加Drools配置类3.4 创建实体类Order3.5 orderScore.drl3.6 编写测试类 4 Drools基础语法4.1 规则…

HTML、CSS 和 JavaScript 常见用法及使用规范

一、HTML 深度剖析 1. 文档类型声明 HTML 文档开头的 <!DOCTYPE html> 声明告知浏览器当前文档使用的是 HTML5 标准。它是文档的重要元信息&#xff0c;能确保浏览器以标准模式渲染页面&#xff0c;避免怪异模式下的兼容性问题。 2. 元数据标签 <meta> 标签&am…

基于CNN+ViT的蔬果图像分类实验

本文只是做一个简单融合的实验&#xff0c;没有任何新颖&#xff0c;大家看看就行了。 1.数据集 本文所采用的数据集为Fruit-360 果蔬图像数据集&#xff0c;该数据集由 Horea Mureșan 等人整理并发布于 GitHub&#xff08;项目地址&#xff1a;Horea94/Fruit-Images-Datase…

Ubuntu24.04安装libgl1-mesa-glx 报错,软件包缺失

在 Ubuntu 24.04 系统中&#xff0c;您遇到的 libgl1-mesa-glx 软件包缺失问题可能是由于该包在最新的 Ubuntu 版本中被重命名为 libglx-mesa0。以下是针对该问题的详细解决方案&#xff1a; 1. 问题原因分析 包名称变更&#xff1a;在 Ubuntu 24.04 中&#xff0c;libgl1-me…

webpack vite

​ 1、webpack webpack打包工具&#xff08;重点在于配置和使用&#xff0c;原理并不高优。只在开发环境应用&#xff0c;不在线上环境运行&#xff09;&#xff0c;压缩整合代码&#xff0c;让网页加载更快。 前端代码为什么要进行构建和打包&#xff1f; 体积更好&#x…

如何在爬虫中合理使用海外代理?在爬虫中合理使用海外ip

我们都知道&#xff0c;爬虫工作就是在各类网页中游走&#xff0c;快速而高效地采集数据。然而如果目标网站分布在多个国家或者存在区域性限制&#xff0c;那靠普通的网络访问可能会带来诸多阻碍。而这时&#xff0c;“海外代理”俨然成了爬虫工程师们的得力帮手&#xff01; …

数据仓库分层存储设计:平衡存储成本与查询效率

数据仓库分层存储不仅是一个技术问题,更是一种艺术:如何在有限的资源下,让数据既能快速响应查询,又能以最低的成本存储? 目录 一、什么是数据仓库分层存储? 二、分层存储的体系架构 1. 数据源层(ODS,Operational Data Store) 2. 数据仓库层(DW,Data Warehouse)…

YOLO学习笔记 | 基于YOLOv8的植物病害检测系统

以下是基于YOLOv8的植物病害检测系统完整技术文档,包含原理分析、数学公式推导及代码实现框架。 基于YOLOv8的智能植物病害检测系统研究 摘要 针对传统植物病害检测方法存在的效率低、泛化性差等问题,本研究提出一种基于改进YOLOv8算法的智能检测系统。通过设计轻量化特征提…

高级语言调用C接口(二)回调函数(4)Python

前面2篇分别说了java和c#调用C接口&#xff0c;参数为回调函数&#xff0c;回调函数中参数是结构体指针。 接下来说下python的调用方法。 from ctypes import * import sysclass stPayResult(Structure):_pack_ 4 # 根据实际C结构体的对齐方式设置&#xff08;常见值为1,4,…

springboot启动动态定时任务

1.自定义定时任务线程池 package com.x.devicetcpserver.global.tcp.tcpscheduler;import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotatio…

pytorch框架认识--手写数字识别

手写数字是机器学习中非常经典的案例&#xff0c;本文将通过pytorch框架&#xff0c;利用神经网络来实现手写数字识别 pytorch中提供了手写数字的数据集&#xff0c;我们可以直接从pytorch中下载 MNIST中包含70000张手写数字图像&#xff1a;60000张用于训练&#xff0c;10000…

WPF 使用依赖注入后关闭窗口程序不结束

原因是在ViewModel中在构造函数中注入了Window 对象&#xff0c;即使没有使用&#xff0c;主窗口关闭程序不会退出&#xff0c;即使 ViewModel 是 AddTransient 注入的。 解决方法&#xff1a;不使用构造函数注入Window&#xff0c;通过GetService获取Window 通过注入对象调用…

用户管理(添加和删除,查询信息,切换用户,查看登录用户,用户组,配置文件)

目录 添加和删除用户 查询用户信息 切换用户 查看当前的操作用户是谁 查看首次登录的用户是谁 用户组&#xff08;对属于同个角色的用户统一管理&#xff09; 新增组 删除组 添加用户的同时&#xff0c;指定组 修改用户的组 组的配置文件&#xff08;/etc/group&…

PyTorch学习-小土堆教程

网络搭建torch.nn.Module 卷积操作 torch.nn.functional.conv2d(input, weight, biasNone, stride1, padding0, dilation1, groups1) 神经网络-卷积层