23种设计模式之【状态机模式】-核心原理与 Java实践

文章目录

状态模式(State Pattern)

状态模式是 23 种设计模式中的一种行为型模式,其核心思想是允许对象在内部状态改变时改变它的行为,使对象看起来好像修改了它的类。这种模式将对象的状态封装为独立的状态类,通过状态切换实现行为的动态变化,避免了使用大量条件判断语句(如if-else或switch-case)。

核心原理

环境类(Context):

持有当前状态的引用,是状态模式的使用者

提供方法供客户端触发状态转换或执行操作

自身不处理状态相关的逻辑,而是委托给当前状态对象
抽象状态(State):

定义所有具体状态的公共接口,声明环境类中可能触发的操作

可以是接口或抽象类,方法对应环境类在不同状态下的行为
具体状态(ConcreteState):

实现抽象状态接口,定义特定状态下的行为逻辑

在执行操作时可能触发状态转换(通过修改环境类的当前状态)

状态模式的核心是 "将状态封装为对象,通过状态对象的切换改变行为",将原本分散在环境类中的状态判断逻辑,拆分到不同的状态类中,使代码更清晰、易维护。

Java 实践示例

以 "订单状态流转" 为例实现状态模式:

订单存在多种状态:待支付、已支付、已发货、已完成、已取消

不同状态下允许的操作不同(如待支付状态可支付或取消,已支付状态可发货等)

通过状态模式封装每种状态的行为及状态转换逻辑

java 复制代码
package com.example.demo;

public class StatePattern {
    public static void main(String[] args) {
        // 创建订单(环境类)
        Order order = new Order();

        System.out.println("=== 初始状态 ===");
        order.getCurrentState();

        // 尝试取消订单(待支付状态可取消)
        System.out.println("\n=== 取消订单 ===");
        order.cancel();
        order.getCurrentState();

        // 重新创建订单并完成全流程
        order = new Order();
        System.out.println("\n=== 新订单流程 ===");
        order.pay();       // 支付
        order.ship();      // 发货
        order.complete();  // 完成
        order.getCurrentState();

        // 尝试在已完成状态执行发货(不允许)
        System.out.println("\n=== 已完成状态执行发货 ===");
        order.ship();
        //=== 初始状态 ===
        //当前订单状态:待支付
        //
        //=== 取消订单 ===
        //订单已取消
        //当前订单状态:已取消
        //
        //=== 新订单流程 ===
        //订单支付成功
        //订单已发货
        //订单已完成
        //当前订单状态:已完成
        //
        //=== 已完成状态执行发货 ===
        //错误:订单已完成,无需发货
    }

    // 抽象状态:订单状态接口
    public interface OrderState {
        // 支付订单
        void pay(Order order);

        // 取消订单
        void cancel(Order order);

        // 发货
        void ship(Order order);

        // 完成订单
        void complete(Order order);

        // 获取状态名称
        String getStateName();
    }

    // 具体状态:待支付
    public static class PendingPaymentState implements OrderState {
        @Override
        public void pay(Order order) {
            // 支付成功,转换为已支付状态
            order.setState(new PaidState());
            System.out.println("订单支付成功");
        }

        @Override
        public void cancel(Order order) {
            // 取消订单,转换为已取消状态
            order.setState(new CancelledState());
            System.out.println("订单已取消");
        }

        @Override
        public void ship(Order order) {
            System.out.println("错误:订单未支付,无法发货");
        }

        @Override
        public void complete(Order order) {
            System.out.println("错误:订单未支付,无法完成");
        }

        @Override
        public String getStateName() {
            return "待支付";
        }
    }

    // 具体状态:已支付
    public static class PaidState implements OrderState {
        @Override
        public void pay(Order order) {
            System.out.println("错误:订单已支付,无需重复支付");
        }

        @Override
        public void cancel(Order order) {
            order.setState(new CancelledState());
            System.out.println("已支付订单取消成功(将安排退款)");
        }

        @Override
        public void ship(Order order) {
            order.setState(new ShippedState());
            System.out.println("订单已发货");
        }

        @Override
        public void complete(Order order) {
            System.out.println("错误:订单未发货,无法完成");
        }

        @Override
        public String getStateName() {
            return "已支付";
        }
    }

    // 具体状态:已发货(其他状态类类似实现)
    public static class ShippedState implements OrderState {
        @Override
        public void pay(Order order) {
            System.out.println("错误:订单已发货,无需支付");
        }

        @Override
        public void cancel(Order order) {
            System.out.println("错误:订单已发货,无法取消");
        }

        @Override
        public void ship(Order order) {
            System.out.println("错误:订单已发货,无需重复发货");
        }

        @Override
        public void complete(Order order) {
            order.setState(new CompletedState());
            System.out.println("订单已完成");
        }

        @Override
        public String getStateName() {
            return "已发货";
        }
    }

    // 具体状态:已完成
    public static class CompletedState implements OrderState {
        // 实现所有方法,已完成状态下大部分操作不允许
        @Override
        public void pay(Order order) {
            System.out.println("错误:订单已完成,无需支付");
        }

        @Override
        public void cancel(Order order) {
            System.out.println("错误:订单已完成,无法取消");
        }

        @Override
        public void ship(Order order) {
            System.out.println("错误:订单已完成,无需发货");
        }

        @Override
        public void complete(Order order) {
            System.out.println("错误:订单已完成,无需重复操作");
        }

        @Override
        public String getStateName() {
            return "已完成";
        }
    }

    // 具体状态:已取消
    public static class CancelledState implements OrderState {
        // 实现所有方法,已取消状态下大部分操作不允许
        @Override
        public void pay(Order order) {
            System.out.println("错误:订单已取消,无法支付");
        }

        @Override
        public void cancel(Order order) {
            System.out.println("错误:订单已取消,无需重复取消");
        }

        @Override
        public void ship(Order order) {
            System.out.println("错误:订单已取消,无法发货");
        }

        @Override
        public void complete(Order order) {
            System.out.println("错误:订单已取消,无法完成");
        }

        @Override
        public String getStateName() {
            return "已取消";
        }
    }

    // 环境类:订单
    public static class Order {
        // 持有当前状态的引用
        private OrderState currentState;

        // 初始化订单为待支付状态
        public Order() {
            this.currentState = new PendingPaymentState();
        }

        // 设置当前状态(供状态类调用以实现状态转换)
        public void setState(OrderState state) {
            this.currentState = state;
        }

        // 委托当前状态处理支付操作
        public void pay() {
            currentState.pay(this);
        }

        // 委托当前状态处理取消操作
        public void cancel() {
            currentState.cancel(this);
        }

        // 委托当前状态处理发货操作
        public void ship() {
            currentState.ship(this);
        }

        // 委托当前状态处理完成操作
        public void complete() {
            currentState.complete(this);
        }

        // 获取当前状态名称
        public void getCurrentState() {
            System.out.println("当前订单状态:" + currentState.getStateName());
        }
    }
}

状态模式的特点

  • 优点:
    消除大量条件判断:将状态相关的逻辑分散到不同状态类,替代冗长的if-else或switch-case
    状态转换清晰:每个状态类负责自身的状态转换逻辑,职责单一
    易于扩展:新增状态只需添加新的状态类,符合开闭原则
    状态封装性好:状态的细节被隐藏在具体状态类中,环境类无需了解
  • 缺点:
    类数量增加:每个状态对应一个类,状态较多时会导致类数量膨胀
    状态转换依赖环境类:状态类需要持有环境类引用才能实现状态转换,增加了耦合

与策略模式的区别:

状态模式:状态的切换由对象内部状态决定,策略通常由客户端主动设置

策略模式:关注不同算法的替换,状态模式关注状态变化导致的行为变化

状态模式的应用场景

  • 状态流转明确的业务对象:
    订单状态、流程状态、审批状态等有明确流转规则的对象
    例如:电商订单(待支付→已支付→已发货→已完成)、请假审批流程
  • 有限状态机(FSM):
    具有有限个状态且状态间转换规则明确的系统
    例如:电梯控制(开门→关门→运行→停止)、交通信号灯(红→黄→绿)
  • 游戏开发:
    游戏角色状态( idle→行走→攻击→受伤→死亡)
    游戏场景状态(加载中→正常→暂停→结束)
  • UI 组件状态:
    按钮状态(可用→禁用→选中→未选中)
    表单输入状态(未编辑→编辑中→验证通过→验证失败)

状态模式特别适合对象行为随状态变化而变化,且状态数量较多、转换逻辑复杂的场景。它通过将状态逻辑封装为独立对象,使系统更易于维护和扩展,是处理状态流转的最佳实践之一。

相关推荐
聪明的笨猪猪7 分钟前
Java JVM “内存(1)”面试清单(含超通俗生活案例与深度理解)
java·经验分享·笔记·面试
Meteors.14 分钟前
23种设计模式——外观模式(Facade Pattern)详解
设计模式·外观模式
胖虎115 分钟前
iOS中的设计模式(九)- 外观模式 用外观模式点一份外卖:Swift 实战讲解
设计模式·外观模式
程序员清风22 分钟前
快手二面:乐观锁是怎么用它来处理多线程问题的?
java·后端·面试
一线大码37 分钟前
SpringBoot 优雅实现接口的多实现类方式
java·spring boot·后端
花伤情犹在42 分钟前
Java Stream 高级应用:优雅地扁平化(FlatMap)递归树形结构数据
java·stream·function·flatmap
yaoxin5211231 小时前
212. Java 函数式编程风格 - Java 编程风格转换:命令式 vs 函数式(以循环为例)
java·开发语言
摇滚侠1 小时前
Spring Boot 3零基础教程,WEB 开发 Thymeleaf 属性优先级 行内写法 变量选择 笔记42
java·spring boot·笔记
滑水滑成滑头1 小时前
**发散创新:多智能体系统的探索与实践**随着人工智能技术的飞速发展,多智能体系统作为当今研究的热点领域,正受到越来越多关注
java·网络·人工智能·python
摇滚侠1 小时前
Spring Boot 3零基础教程,WEB 开发 Thymeleaf 总结 热部署 常用配置 笔记44
java·spring boot·笔记