展开菜单
首页 精品内容 本月促销 装机必备 Windows PDF教程 macOS软件 IOS软件 Android AI 专题
全部分类

当前位置:

首页 > 编程开发 > Java中状态机模式的两种实现方式详解

Java中状态机模式的两种实现方式详解

一、什么是状态机 先说说状态机这个概念。它本质上是一个数学模型,用来描述一个对象在其生命周期里,会经历哪些状态,以及在什么条件下从一个状态跳到另一个状态。说白了,就是给对象画一张“状态流转地图”。 理解状态机,抓住三个核心要素就够了: 状态(State):对象当前处于什么情形。比如订单是“待支付”还

本文目录

    一、什么是状态机

    先说说状态机这个概念。它本质上是一个数学模型,用来描述一个对象在其生命周期里,会经历哪些状态,以及在什么条件下从一个状态跳到另一个状态。说白了,就是给对象画一张“状态流转地图”。

    Ja va中状态机模式的两种实现方式详解

    理解状态机,抓住三个核心要素就够了:

    • 状态(State):对象当前处于什么情形。比如订单是“待支付”还是“已发货”。
    • 事件(Event):触发状态变化的动作或条件。比如用户点击了“支付”按钮。
    • 转换(Transition):从一个状态到另一个状态的过程。比如“待支付”遇到“支付”事件,就变成“已支付”。

    用一句话概括:在某个状态下,发生了某个事件,对象转换到了另一个状态。就这么简单。

    二、状态机的两种实现方式

    1. 显式状态机

    显式状态机,就是通过独立的状态机框架或代码结构来管理状态转换。所有状态流转规则都集中定义、显式声明,一目了然。

    特点:

    • 状态和转换规则集中配置
    • 有明确的状态转换表或图
    • 非法转换会被统一拦截
    • 通常有框架支持(如 Spring StateMachine)

    2. 隐式状态机

    隐式状态机则相反——没有独立的状态机组件,状态值就存在数据库的一个字段里,流转逻辑分散在各个业务方法的 if/else 或 switch 中。你看代码的时候,得一个一个方法去翻,才知道哪些状态能转到哪些状态。

    特点:

    • 状态就是一个普通字段
    • 转换逻辑散落在各处业务代码中
    • 没有统一的规则校验
    • 实现简单,但维护成本会随着业务增长而直线上升

    三、隐式状态机的典型实现方式

    这是大多数业务系统中最常见的做法。用一个订单状态的例子来说明:

    数据库层面

    CREATE TABLE orders (
        id INT PRIMARY KEY,
        status INT NOT NULL DEFAULT 0 COMMENT '0=待支付, 1=已支付, 2=已发货, 3=已完成, 4=已取消'
    );

    枚举定义

    public enum OrderStatus {
        UNPAID(0, "待支付"),
        PAID(1, "已支付"),
        SHIPPED(2, "已发货"),
        COMPLETED(3, "已完成"),
        CANCELLED(4, "已取消");
    
        private Integer code;
        private String desc;
    }
    

    业务代码中的状态流转

    public void payOrder(Integer orderId) {
        Order order = orderRepository.findById(orderId);
        // 隐式校验:只有待支付才能支付
        if (!OrderStatus.UNPAID.getCode().equals(order.getStatus())) {
            throw new BusinessException("当前状态不允许支付");
        }
        order.setStatus(OrderStatus.PAID.getCode());
        orderRepository.sa ve(order);
    }
    
    public void shipOrder(Integer orderId) {
        Order order = orderRepository.findById(orderId);
        // 隐式校验:只有已支付才能发货
        if (!OrderStatus.PAID.getCode().equals(order.getStatus())) {
            throw new BusinessException("当前状态不允许发货");
        }
        order.setStatus(OrderStatus.SHIPPED.getCode());
        orderRepository.sa ve(order);
    }
    
    public void cancelOrder(Integer orderId) {
        Order order = orderRepository.findById(orderId);
        // 隐式校验:已发货和已完成不能取消
        if (OrderStatus.SHIPPED.getCode().equals(order.getStatus())
            || OrderStatus.COMPLETED.getCode().equals(order.getStatus())) {
            throw new BusinessException("当前状态不允许取消");
        }
        order.setStatus(OrderStatus.CANCELLED.getCode());
        orderRepository.sa ve(order);
    }
    

    状态转换图:

    UNPAID(0) ──[支付]──→ PAID(1) ──[发货]──→ SHIPPED(2) ──[确认收货]──→ COMPLETED(3)

    │ │

    └──[取消]──→ CANCELLED(4) ←──[取消]──┘

    这就是隐式状态机——没有一个集中的地方定义“什么状态可以转到什么状态”,全靠每个业务方法里的 if 判断来保证。状态少的时候还能凑合,一旦状态多了,维护起来就头疼了。

    四、显式状态机的实现方式

    方式一:状态转换表

    把所有合法的转换关系集中定义在一张表里,代码瞬间清晰:

    public class OrderStateMachine {
    
        // 转换规则表:Map<当前状态, Map<事件, 目标状态>>
        private static final Map> TRANSITIONS = new HashMap<>();
    
        static {
            // 待支付状态下的合法转换
            Map unpaidTransitions = new HashMap<>();
            unpaidTransitions.put("PAY", 1);       // 支付 → 已支付
            unpaidTransitions.put("CANCEL", 4);    // 取消 → 已取消
            TRANSITIONS.put(0, unpaidTransitions);
    
            // 已支付状态下的合法转换
            Map paidTransitions = new HashMap<>();
            paidTransitions.put("SHIP", 2);        // 发货 → 已发货
            paidTransitions.put("CANCEL", 4);      // 取消 → 已取消
            TRANSITIONS.put(1, paidTransitions);
    
            // 已发货状态下的合法转换
            Map shippedTransitions = new HashMap<>();
            shippedTransitions.put("CONFIRM", 3);  // 确认 → 已完成
            TRANSITIONS.put(2, shippedTransitions);
        }
    
        /**
         * 执行状态转换.
         */
        public static Integer transition(Integer currentState, String event) {
            Map allowed = TRANSITIONS.get(currentState);
            if (allowed == null || !allowed.containsKey(event)) {
                throw new IllegalStateException(
                    "非法状态转换: 状态=" + currentState + ", 事件=" + event);
            }
            return allowed.get(event);
        }
    }
    

    使用起来也很简单:

    public void payOrder(Integer orderId) {
        Order order = orderRepository.findById(orderId);
        // 由状态机统一校验和转换
        Integer newStatus = OrderStateMachine.transition(order.getStatus(), "PAY");
        order.setStatus(newStatus);
        orderRepository.sa ve(order);
    }
    

    方式二:枚举 + 方法

    还有一种更优雅的方式——把状态转换逻辑直接写在枚举里:

    public enum OrderStatus {
        UNPAID(0) {
            @Override
            public OrderStatus onPay() { return PAID; }
            @Override
            public OrderStatus onCancel() { return CANCELLED; }
        },
        PAID(1) {
            @Override
            public OrderStatus onShip() { return SHIPPED; }
            @Override
            public OrderStatus onCancel() { return CANCELLED; }
        },
        SHIPPED(2) {
            @Override
            public OrderStatus onConfirm() { return COMPLETED; }
        },
        COMPLETED(3),
        CANCELLED(4);
    
        private Integer code;
    
        // 默认实现:抛异常表示不允许该操作
        public OrderStatus onPay() { throw new IllegalStateException("当前状态不允许支付"); }
        public OrderStatus onShip() { throw new IllegalStateException("当前状态不允许发货"); }
        public OrderStatus onConfirm() { throw new IllegalStateException("当前状态不允许确认"); }
        public OrderStatus onCancel() { throw new IllegalStateException("当前状态不允许取消"); }
    }
    

    这样每个状态自己就知道哪些操作是合法的,调用方不需要关心具体规则,直接调方法就行。

    五、两种方式的对比

    维度隐式状态机显式状态机
    实现成本低,直接写 if/else中等,需要定义转换规则
    可读性差,状态规则分散在各方法中好,规则集中一目了然
    维护成本状态少时低,状态多时急剧上升稳定,新增状态只需加规则
    安全性容易遗漏校验导致非法转换统一拦截非法转换
    适用场景状态少(3-5个)且变化少状态多或流转规则复杂

    从这张表可以看出来,选择哪种方式取决于你的业务复杂度。如果只有两三个状态,用隐式完全够用;一旦状态超过五个,或者转换规则频繁变动,显式状态机才是长久之计。

    六、状态机中的常见概念

    守卫条件(Guard)

    在实际业务中,状态转换往往不是“事件触发就转”这么简单,还需要额外的校验。比如,订单要发货,前提是库存充足。这种校验就叫守卫条件:

    // 事件是"发货",但还需要守卫条件:库存充足
    public Integer transition(Integer currentState, String event, Order order) {
        if ("SHIP".equals(event) && order.getStock() <= 0) {
            throw new BusinessException("库存不足,无法发货");
        }
        return TRANSITIONS.get(currentState).get(event);
    }
    

    转换动作(Action)

    状态转换时,通常还需要附带执行一些业务操作。比如订单取消时,要自动退款、发通知:

    // 转换到"已取消"时,自动执行退款
    public void cancelOrder(Order order) {
        Integer newStatus = OrderStateMachine.transition(order.getStatus(), "CANCEL");
        order.setStatus(newStatus);
        // 转换动作
        refundService.refund(order.getPaymentId());
        notificationService.notifyUser(order.getUserId(), "订单已取消");
    }
    

    入口动作 / 出口动作(Entry/Exit Action)

    有些动作与触发事件无关,只要进入某个状态就固定执行。比如无论从哪个状态进入“已取消”,都要发通知并释放库存:

    // 无论从哪里进入"已取消"状态,都发通知
    private void onEnterCancelled(Order order) {
        notificationService.notifyUser(order.getUserId(), "订单已取消");
        inventoryService.releaseStock(order.getItems());
    }
    

    状态回退(Rollback)

    有时候业务需要回退,比如物流拦截成功,需要从“已发货”回退到“已支付”。回退不只是改状态字段,还要撤销之前执行的动作:

    // 从已发货回退到已支付(例如物流拦截成功)
    public void rollbackShipment(Order order) {
        if (!OrderStatus.SHIPPED.getCode().equals(order.getStatus())) {
            throw new BusinessException("只有已发货状态才能回退");
        }
        order.setStatus(OrderStatus.PAID.getCode());
        // 撤销动作:取消物流单、恢复库存
        logisticsService.cancelShipment(order.getLogisticsNo());
        inventoryService.restoreStock(order.getItems());
    }
    

    七、涉及多字段联动的复合状态

    实际业务中,一个对象往往有多个状态维度,形成复合状态。比如一个订单既有“签章状态”,又有“同步状态”:

    // 两个独立的状态维度
    private Integer signStatus;    // 签章状态
    private Integer syncYcStatus;  // 同步状态
    
    // 复合状态:只有签章完成且已同步才算"流程结束"
    // 回退时两个维度可能都需要回退
    

    这种场景下,有几个关键点要特别注意:

    • 两个状态之间是否有依赖关系(比如同步必须在签章完成之后才能进行)
    • 回退时是否需要联动回退(签章回退了,同步状态是不是也要跟着回退)
    • 是否有外部系统已经接收了数据(如果是不可逆操作,比如已经发送给第三方,回退就要特别谨慎)

    八、总结

    状态机本质上解决的是对象生命周期管理的问题。不管用哪种方式实现,核心关注点就那么几个:

    1. 有哪些状态 → 用枚举定义清楚,别漏掉
    2. 什么事件触发什么转换 → 转换规则要集中管理,别散落在各处
    3. 转换时要做什么 → 把动作和转换绑定,别漏掉重要的业务操作
    4. 非法转换怎么办 → 统一校验拦截,别等出bug了再补
    5. 需要回退怎么办 → 设计好逆向转换和补偿动作,别让回退变成新的麻烦

    把这五点想清楚,状态机这关就算过了。

    本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系bd@zhengruan.com
    作者最新文章
    编程开发
    相关文章 更多
    精品专题 更多
    装机必备

    正软商城装机必备专区,精选办公、浏览器、安全防护、影音播放、压缩解压、设计创作和系统工具等电脑常用正版软件,帮助用户快速完成新电脑软件配置。

    Windows

    正软商城Windows软件专区,汇集适用于Windows电脑的办公、设计、安全防护、影音播放、开发工具和系统优化软件,提供软件介绍、系统要求、正版授权及购买下载服务。

    PDF教程

    正软商城PDF教程频道提供PDF编辑、转换、合并、拆分、压缩及格式处理方法,同时介绍常用PDF软件和工具的使用技巧。

    macOS软件

    正软商城macOS软件专区,精选适用于Mac电脑的办公、设计、影音、效率、开发和系统工具,提供软件功能介绍、macOS兼容版本、正版授权及购买下载服务。

    IOS软件

    正软商城iOS软件专区,精选适用于iPhone和iPad的办公、学习、影音、设计、效率及AI应用,提供功能介绍、适用设备、系统要求和正版获取方式等信息。

    AI

    正软商城AI软件专区,汇集AI写作、AI绘画、AI视频、AI办公、AI编程、AI翻译、智能客服和数据分析等人工智能工具,提供功能介绍、适用平台、收费方式及正版购买信息。

    Mac软件 更多
    IntelliJ IDEA macOS版
    IntelliJ IDEA macOS版

    IntelliJ IDEA 是 JetBrains 推出的专业集成开发环境,重点服务于 Java、Kotlin 与 JVM 项目开发。软件集成代码补全、静态检查、重构、调试、测试、版本控制及构建工具,并可借助插件扩展语言和框架支持。

    PyCharm macOS版
    PyCharm macOS版

    JetBrains PyCharm 是面向 Python 开发者的集成开发环境,提供智能补全、代码检查、重构、调试、测试、版本控制及虚拟环境管理功能。Mac 版兼容 Intel 与 Apple 芯片,核心功能可免费使用。

    WebStorm macOS版
    WebStorm macOS版

    JetBrains WebStorm 是面向 JavaScript、TypeScript 和现代 Web 技术的专业集成开发环境,可智能理解项目结构,提供代码补全、重构、错误检查、运行调试、测试及 Git 工具。

    After Effects macOS版
    After Effects macOS版

    Adobe After Effects 是面向动态图形、影视特效与视频合成的专业创作软件。它提供关键帧动画、遮罩抠像、运动跟踪、三维空间、文字动画和表达式等工具,并可与 Premiere Pro、Photoshop、Illustrator

    Audition macOS版
    Audition macOS版

    Adobe Audition 是面向播客、影视后期、音乐制作及内容创作者的专业音频工作站,提供波形精修、多轨录制与混音、频谱编辑、降噪修复、响度匹配和效果处理工具,并可与 Adobe Premiere 协同完成视频声音制作。

    Bridge macOS版
    Bridge macOS版

    Adobe Bridge 是面向摄影师、设计师及内容团队的免费数字资产管理工具,可集中预览照片、视频和 Adobe 项目文件,并利用评级、标签、关键词、元数据、筛选与收藏集完成分类检索。它还支持批量重命名、格式导出、相机导入及 Camera

    Illustrator macOS版
    Illustrator macOS版

    Adobe Illustrator 是 Adobe 推出的专业矢量图形设计软件,适合在 Mac 上制作标志、图标、插画、包装、信息图及印刷版面。它以路径和锚点构建可无损缩放的图形,并提供钢笔、形状、文字、图像描摹、渐变、画板及生成式功能。

    InDesign macOS版
    InDesign macOS版

    Adobe InDesign 是面向印刷品与数字出版物的专业版面设计软件,可在 Mac 上制作书籍、杂志、宣传册、海报、报告及交互式文档。它提供精细的文字样式、网格、母版、长文档管理和印前输出能力。

    Lightroom Classic macOS版
    Lightroom Classic macOS版

    Adobe Lightroom Classic 是面向桌面摄影工作流的照片管理与后期处理软件,可将原始照片保存在本地硬盘,通过目录、关键词、评分和收藏夹高效整理图库,并提供 RAW 冲印、蒙版、镜头校正、批量同步及多格式导出等功能。

    Media Encoder macOS版
    Media Encoder macOS版

    Adobe Media Encoder 是 Adobe 推出的专业音视频编码与转码工具,可通过队列、预设和监视文件夹批量完成格式转换、代理文件创建及多平台成片输出,并与 Premiere Pro、After Effects 等软件紧密协作。

    Photoshop macOS版
    Photoshop macOS版

    Adobe Photoshop 是面向摄影师、设计师和内容创作者的专业图像处理软件,提供图层、蒙版、选区、修复、调色、文字排版、智能对象及生成式编辑等能力。Mac 版支持 Intel 与 Apple Silicon 处理器。

    Premiere Pro macOS版
    Premiere Pro macOS版

    Adobe Premiere Pro 是面向专业视频制作的非线性剪辑软件,提供多轨时间线、调色、音频处理、字幕、代理工作流和多格式输出能力,并可与 After Effects、Audition、Photoshop 及 Frame.io 协同

    WINDOWS 更多
    IntelliJ IDEA Windows版
    IntelliJ IDEA Windows版

    JetBrains IntelliJ IDEA 是以 Java、Kotlin 和 JVM 项目为核心的专业集成开发环境,提供智能补全、代码检查、安全重构、调试、测试、版本控制及构建工具集成。统一发行版的核心功能可免费用于商业和非商业项目,

    PhpStorm Windows版
    PhpStorm Windows版

    PhpStorm 是 JetBrains 面向 PHP 与现代 Web 开发打造的专业集成开发环境,提供代码补全、静态检查、重构、调试、测试、数据库、版本控制及前端语言支持。Windows 用户可直接下载安装程序,

    PyCharm Windows版
    PyCharm Windows版

    PyCharm 是 JetBrains 推出的 Python 集成开发环境,提供智能代码补全、错误检查、重构、调试、测试、Git、终端及 Jupyter Notebook 支持。统一版安装后可体验 30 天 Pro 功能,

    WebStorm Windows版
    WebStorm Windows版

    WebStorm 是 JetBrains 面向 JavaScript、TypeScript 和现代 Web 技术打造的集成开发环境。它提供项目级代码分析、智能补全、安全重构、导航搜索,并集成调试、测试、终端、Git 与常用前端工具,

    Photoshop Windows版
    Photoshop Windows版

    Adobe Photoshop 是面向摄影师、设计师和内容创作者的专业图像处理工具,可在 Windows 上完成照片修饰、选区抠图、图层合成、文字排版、绘画及生成式编辑。软件采用订阅授权,由 Creative Cloud 管理安装、更新与许

    InDesign Windows版
    InDesign Windows版

    Adobe InDesign 是面向印刷与数字出版的专业页面排版工具,可制作书籍、杂志、宣传册、海报、交互式 PDF 和电子书。它提供精细的文字样式、多页面管理、印前检查及多格式输出能力,并能与 Photoshop、Illustrator

    Illustrator Windows版
    Illustrator Windows版

    Adobe Illustrator 是用于绘制矢量图形、插画、图标、徽标和版式的专业设计工具。它以路径和锚点为核心,作品放大后仍能保持清晰,并提供画板、文字、渐变、图像描摹及精确变换等功能,适合品牌视觉、印刷物料、数字界面和商业插画创作。

    Bridge Windows版
    Bridge Windows版

    Adobe Bridge 是 Adobe 推出的创意资产管理工具,可集中预览、分类和查找照片、视频、PDF及多种设计文件,并支持元数据、关键词、评级、批量重命名和格式导出。它可与 Photoshop、Illustrator 等应用衔接,

    Lightroom Classic Windows版
    Lightroom Classic Windows版

    Adobe Lightroom Classic 是面向 Windows 桌面摄影工作流的照片管理与无损编辑工具,可通过目录集中整理大型图库,并完成 RAW 显影、局部蒙版、批量调整、打印和多格式导出。它强调本地文件管理与精细控制,

    Acrobat Pro Windows版
    Acrobat Pro Windows版

    Adobe Acrobat Pro 是面向专业 PDF 工作的综合解决方案,可在 Windows 中创建、编辑、转换、比较、整理和保护文档,并支持表单、电子签名、扫描件文字识别及敏感信息永久遮盖。订阅还包含网页、移动服务和云端协作能力,

    After Effects Windows版
    After Effects Windows版

    Adobe After Effects 是面向动态图形、动画与影视视觉特效制作的专业工具,可完成关键帧动画、图层合成、遮罩跟踪、抠像、文字动画和二维三维元素整合。Windows 版通过 Adobe Creative Cloud 安装及更新,

    Media Encoder Windows版
    Media Encoder Windows版

    Adobe Media Encoder 是 Adobe 面向视频与音频制作流程提供的专业编码和转码工具,可批量处理媒体文件、创建代理、套用输出预设并监控文件夹自动执行任务。它与 Premiere、After Effects、Audition