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

news2025/4/18 11:55:58
引言

状态模式(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 {
    @Override
    public void handle(Context context) {
        System.out.println("处理状态A的行为");
        context.setState(new ConcreteStateB()); // 状态转移
    }
}

// 具体状态B
class ConcreteStateB implements State {
    @Override
    public 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行为,切换到B
        context.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 {
    @Override
    public void confirm(OrderContext context) {
        System.out.println("订单支付成功");
        context.setState(new PaidState());
    }
    
    @Override
    public void cancel(OrderContext context) {
        System.out.println("订单已取消");
        context.setState(new CancelledState());
    }
    
    @Override
    public 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 {
    @Override
    public void change(TrafficLight light) {
        light.setState(new GreenLight());
    }
    
    @Override
    public 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 {
    @Override
    public void play(MediaPlayer player) {
        System.out.println("已在播放状态");
    }
    
    @Override
    public void pause(MediaPlayer player) {
        System.out.println("暂停播放");
        player.setState(new PausedState());
    }
    
    @Override
    public 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.coloradmin.cn/o/2336181.html

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

相关文章

高性能内存kv数据库Redis

目录 引言 一.Redis相关命令详解及其原理 1.redis是什么? 2.redis中存储数据的数据结构都有哪些? 3.redis的存储结构(KV) 4.reidis中value编码 5.string的基本原理和相关命令 5.1基本原理 5.2基础命令 5.3string存储结构 …

性能优化实践

4.1 大规模量子态处理的性能优化 背景与问题分析 量子计算中的大规模量子态处理(如量子模拟、量子态可视化)需要高效计算和实时渲染能力。传统图形API(如WebGL)在处理高维度量子态时可能面临性能瓶颈,甚至崩溃(如表格中14量子比特时WebGL的崩溃)。而现代API(如WebGPU…

使用wpa_cli和wpa_supplicant配置Liunx开发板的wlan0无线网

目录 1 简单介绍下wpa_cli和wpa_supplicant 1.1 wpa_supplicant 简介 1.2 wpa_cli 简介 1.3 它们之间的关系 2 启动wpa_supplicant 3 使用rz工具把wpa_cli命令上传到开发板 4 用wpa_cli配置网络 参考文献: 1 简单介绍下wpa_cli和wpa_supplicant 1.1 wpa_su…

C++Cherno 学习笔记day19 [76]-[80] std::optional、variant、any、如何让C++及字符串运行得更快

b站Cherno的课[76]-[80] 一、如何处理OPTIONAL数据 std::optional二、单一变量存放多类型的数据 std::variant三、如何存储任意类型的数据 std::any四、如何让C运行得更快五、如何让C字符串更快 一、如何处理OPTIONAL数据 std::optional std::optional C17 数据是否存在是可选…

【项目日记(一)】-仿mudou库one thread oneloop式并发服务器实现

1、模型框架 客户端处理思想:事件驱动模式 事件驱动处理模式:谁触发了我就去处理谁。 ( 如何知道触发了)技术支撑点:I/O的多路复用 (多路转接技术) 1、单Reactor单线程:在单个线程…

OpenCV 图形API(35)图像滤波-----中值模糊函数medianBlur()

操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 使用中值滤波器模糊图像。 该函数使用带有 ksizeksize 开口的中值滤波器来平滑图像。多通道图像的每个通道都是独立处理的。输出图像必须与输入…

视觉slam框架从理论到实践-第一节绪论

从opencv的基础实现学习完毕后,接下来依照视觉slam框架从理论到实践(第二版)的路线进行学习,主要以学习笔记的形式进行要点记录。 目录 1.数据里程计 2.后端优化 3.回环检测 4.建图 在视觉SLAM 中整体作业流程可分为&#xff1…

图论--DFS搜索图/树

目录 一、图的存储结构 二、题目练习 846. 树的重心 - AcWing题 dfs,之前学习的回溯算法好多都是用dfs实现搜索的(把题目抽象成树形结构来搜索),其实 回溯算法就是 深搜,只不过针对某一搜索场景 我们给他一个更细分…

算法复习(二分+离散化+快速排序+归并排序+树状数组)

一、二分算法 二分算法,堪称算法世界中的高效查找利器,其核心思想在于利用数据的有序性,通过不断将查找区间减半,快速定位目标元素或满足特定条件的位置。 1. 普通二分 普通二分适用于在有序数组中查找特定元素的位置。我们可以…

VSCode写java时常用的快捷键

首先得先安好java插件 1、获取返回值 这里是和idea一样的快捷键的,都是xxxx.var 比如现在我new一个对象 就输入 new MbDo().var // 点击回车即可变成下面的// MbDo mbDo new MbDo()//以此类推get方法也可获取 mbDo.getMc().var // 点击回车即可变成下面的 // St…

使用 Node.js、Express 和 React 构建强大的 API

了解如何使用 Node.js、Express 和 React 创建一个强大且动态的 API。这个综合指南将引导你从设置开发环境开始,到集成 React 前端,并利用 APIPost 进行高效的 API 测试。无论你是初学者还是经验丰富的开发者,这篇文章都适合你。 今天&#…

深度学习入门:神经网络的学习

目录 1 从数据中学习1.1 数据驱动1.2 训练数据和测试数据 2损失函数2.1 均方误差2.2 交叉熵误差2.3 mini-batch学习2.4 mini-batch版交叉熵误差的实现2.5 为何要设定损失函数 3 数值微分3.1 数值微分3.3 偏导数 4 梯度4.1 梯度法4.2 神经网络的梯度 5 学习算法的实现5.1 2层神经…

OSI参考模型和TCP/IP模型

1.OSI参考模型 OSI模型: OSI参考模型有7层,自下而上依次为物理层,数据链路层,网络层,传输层,会话层,表示层,应用层。(记忆口诀:物联网叔会用)。低…

人工智能中的卷积神经网络(CNN)综述

文章目录 前言 1. CNN的基本原理 1.1 卷积层 1.2 池化层 1.3 全连接层 2. CNN的发展历程 2.1 LeNet-5 2.2 AlexNet 2.3 VGGNet 2.4 ResNet 3. CNN的主要应用 3.1 图像分类 3.2 目标检测 3.3 语义分割 3.4 自然语言处理 4. 未来研究方向 4.1 模型压缩与加速 4.2 自监督学习 4.3 …

WordPress - 此站点出现严重错误

本篇讲 当WordPress出现 此站点出现严重错误 时,该如何解决。 目录 1,现象 2, FAQ 3,管理Menu无法打开 下面是详细内容。 1,现象 此站点出现严重错误(このサイトで重大なエラーが発生しました&#x…

在pycharm中搭建yolo11分类检测系统1--PyQt5学习(一)

实验条件:pycharm24.3autodlyolov11环境PyQt5 如果pycharm还没有配PyQt5的话就先去看我原先写的这篇博文: PyQT5安装搭配QT DesignerPycharm)-CSDN博客 跟练参考文章: 目标检测系列(四)利用pyqt5实现yo…

【经验记录贴】使用配置文件提高项目的可维护性

mark一下。 整体修改前后如下: 课题: 在项目中有一个支持的文件类型的FILE_TYPE的定义, 这个是写死在主程序中,每次增加可以支持的文件类型的时候,都需要去修改主程序中这个FILGE_TYPE的定义。 主程序修改其实不太花时…

SOME/IP中”客户端消费“及”服务端提供”的解析

先上结论 AREthAddConsumedEventGroup-->客户端的函数-->谁调用 Consumed函数,谁就是消费者 AREthAddProvidedEventGroup-->服务端的函数-->谁调用 Provided函数,谁就是服务端 Server 端:AREthAddProvidedEventGroup → 声明 &…

Linux 深入浅出信号量:从线程到进程的同步与互斥实战指南

知识点1【信号量概述】 信号量是广泛用于进程和线程间的同步和互斥。信号量的本质 是一个非负的整数计数器,它被用来控制对公共资源的访问 当信号量值大于0的时候,可以访问,否则将阻塞。 PV原语对信号量的操作,一次P操作使信号…

Oracle数据库数据编程SQL<9.1 数据库逻辑备份和迁移exp和imp之导出、导入>

EXP (Export) 和 IMP (Import) 是 Oracle 提供的传统数据导出导入工具,用于数据库逻辑备份和迁移。尽管在较新版本中已被 Data Pump (EXPDP/IMPDP) 取代,但在某些场景下仍然有用。 目录 一、EXP 导出工具 1. 基本语法 2. 常用参数说明 3. 导出模式 3.1 表模式导出 3.2 用…