rokevin
移动
前端
语言
  • 基础

    • Linux
    • 实施
    • 版本构建
  • 应用

    • WEB服务器
    • 数据库
  • 资讯

    • 工具
    • 部署
开放平台
产品设计
  • 人工智能
  • 云计算
计算机
其它
GitHub
移动
前端
语言
  • 基础

    • Linux
    • 实施
    • 版本构建
  • 应用

    • WEB服务器
    • 数据库
  • 资讯

    • 工具
    • 部署
开放平台
产品设计
  • 人工智能
  • 云计算
计算机
其它
GitHub
  • 状态模式(State Pattern)

  • 定义
  • 意图
  • 结构
  • 类图(Mermaid 版)
  • 时序图(Mermaid 版)
  • 模式分析
    • 1. 核心逻辑:委托与双分派
    • 2. 与策略模式的关键区别
  • 优点
  • 缺点
  • 适用环境
  • 模式应用
    • 1. 业务场景
    • 2. 框架源码
  • 模式扩展
    • 1. 状态管理器(State Manager)
    • 2. 状态持久化
    • 3. 分层状态(Hierarchical State)
  • Android 中的应用
    • 1. MediaPlayer 状态管理
    • 2. View 状态与 StateListDrawable
    • 3. Activity 生命周期(类状态模式)
    • 4. 自定义 View 状态管理
  • 代码实现 手机状态管理
    • 1. 步骤 1:定义抽象状态接口(PhoneState)
    • 2. 步骤 2:实现具体状态类
      • 关机状态(PoweredOffState)
      • 开机状态(PoweredOnState)
      • 通话状态(CallingState)
    • 3. 步骤 3:实现环境类(Phone)
    • 4. 步骤 4:客户端测试
    • 5. 运行结果
  • 代码实现 Android 客户端订单状态
    • 功能场景
    • 实现架构
    • 完整代码实现
      • 1. 订单模型与状态接口
      • 2. 具体状态实现
      • 3. 状态管理器与操作常量
      • 4. ViewModel 与 UI 实现
    • 实现说明
      • 核心设计亮点
      • 状态流转测试流程
    • 扩展建议
  • 总结

状态模式(State Pattern)

状态模式是行为型设计模式的核心成员,其核心思想是将对象的状态封装为独立类,让对象在不同状态下表现出不同行为(仿佛 “切换了自身类型”),同时将状态切换逻辑委托给具体状态类,彻底消除代码中冗长的 if-else 或 switch-case 判断。

定义

官方定义(参考《设计模式:可复用面向对象软件的基础》): Allow an object to alter its behavior when its internal state changes. The object will appear to change its class. (当对象的内部状态发生改变时,允许它改变自己的行为,这个对象看起来就像是改变了它的类一样。)

通俗理解: 以 “手机” 为例,它有 “开机”“关机”“待机”“通话” 4 种状态 ——

  • 关机状态:仅支持 “开机” 操作,不支持 “通话”“待机”;
  • 开机状态:支持 “待机”“通话” 操作,不支持 “重复开机”;
  • 通话状态:支持 “挂断” 操作,不支持 “关机”。 状态模式会将每种状态的 “可执行操作” 和 “状态切换规则” 封装成独立类,手机对象只需委托当前状态类处理操作,无需自己判断 “我现在能做什么”。

意图

状态模式的核心目标是解决以下问题:

  1. 消除状态相关的条件判断:避免对象因状态过多而出现 if-else 嵌套(如 if (state == 待支付) { ... } else if (state == 已支付) { ... }),降低代码复杂度;
  2. 封装状态与行为:将 “状态” 和 “该状态下的行为” 强绑定,符合单一职责原则(每个状态类只负责自身逻辑);
  3. 简化状态切换:状态切换逻辑由具体状态类控制(而非分散在环境类中),新增 / 修改状态时无需改动原有代码,符合开闭原则。

结构

状态模式包含 3 个核心角色,复杂场景会扩展 “状态管理器”,各角色职责清晰:

角色名称核心职责
环境类(Context)1. 持有当前状态的引用;2. 对外暴露业务接口(如 “开机”“通话”),并委托给当前状态处理;3. 提供 setState() 方法,允许状态类修改自身状态。
抽象状态(State)定义所有具体状态的统一接口,声明环境类需委托的行为(如 handlePowerOn()、handleCall())。
具体状态(ConcreteState)1. 实现抽象状态的接口,定义该状态下的具体行为(如 “关机状态下开机”);2. 负责状态切换(如 “关机→开机”)。
(可选)状态管理器统一管理所有状态实例(如单例池),避免重复创建状态对象,简化状态获取逻辑。

类图(Mermaid 版)

以 “手机状态管理” 为场景(关机→开机→待机→通话),用 Mermaid 类图展示状态模式结构:

classDiagram
    direction TB

    %% 1. 环境类(Context):手机对象,持有当前状态
    class Phone {
        - phoneId: String
        - currentState: PhoneState  // 核心:持有当前状态引用
        - battery: int  // 电量(辅助属性)
        + Phone(phoneId: String)
        + powerOn(): void  // 对外接口:开机
        + powerOff(): void  // 对外接口:关机
        + makeCall(): void  // 对外接口:打电话
        + endCall(): void  // 对外接口:挂断电话
        + setCurrentState(state: PhoneState): void  // 允许状态切换
        + getPhoneInfo(): String  // 辅助:获取手机信息
    }

    %% 2. 抽象状态(State):定义手机行为接口
    class PhoneState {
        <<interface>>
        + handlePowerOn(phone: Phone): void  // 处理开机
        + handlePowerOff(phone: Phone): void  // 处理关机
        + handleMakeCall(phone: Phone): void  // 处理打电话
        + handleEndCall(phone: Phone): void  // 处理挂断
        + getStateName(): String  // 辅助:获取状态名称
    }

    %% 3. 具体状态(ConcreteState):实现各状态逻辑
    class PoweredOffState {
        - static INSTANCE: PoweredOffState  // 单例:避免重复创建
        + static getInstance(): PoweredOffState
        + handlePowerOn(phone: Phone): void  // 关机→开机
        + handlePowerOff(phone: Phone): void  // 关机不支持重复关机
        + handleMakeCall(phone: Phone): void  // 关机不支持打电话
        + handleEndCall(phone: Phone): void  // 关机不支持挂断
        + getStateName(): String
    }

    class PoweredOnState {
        - static INSTANCE: PoweredOnState
        + static getInstance(): PoweredOnState
        + handlePowerOn(phone: Phone): void  // 开机不支持重复开机
        + handlePowerOff(phone: Phone): void  // 开机→关机
        + handleMakeCall(phone: Phone): void  // 开机→通话
        + handleEndCall(phone: Phone): void  // 开机不支持挂断(未通话)
        + getStateName(): String
    }

    class CallingState {
        - static INSTANCE: CallingState
        + static getInstance(): CallingState
        + handlePowerOn(phone: Phone): void  // 通话中不支持开机
        + handlePowerOff(phone: Phone): void  // 通话中不支持关机
        + handleMakeCall(phone: Phone): void  // 通话中不支持重复打电话
        + handleEndCall(phone: Phone): void  // 通话→开机(待机)
        + getStateName(): String
    }

    %% 角色关系
    Phone "1" --> "1" PhoneState : 持有当前状态 >
    PoweredOffState ..|> PhoneState
    PoweredOnState ..|> PhoneState
    CallingState ..|> PhoneState

时序图(Mermaid 版)

以 “用户开机→打电话→挂断” 为场景,展示状态模式的交互流程,体现委托逻辑和状态切换:

sequenceDiagram
    participant Client as 客户端(用户)
    participant Phone as 环境类(手机)
    participant OffState as 具体状态(关机)
    participant OnState as 具体状态(开机)
    participant CallState as 具体状态(通话)

    %% 1. 初始化:创建手机,默认状态为“关机”
    Client->>Phone: 1. new Phone("P12345")
    Note over Phone: 初始化 currentState = OffState.getInstance()
    Phone-->>Client: 手机创建成功,当前状态:关机

    %% 2. 用户触发开机操作
    Client->>Phone: 2. powerOn()  // 调用手机开机接口
    Note over Phone: 委托当前状态(关机)处理

    %% 3. 手机委托关机状态处理开机
    Phone->>OffState: 3. handlePowerOn(this)
    Note over OffState: 1. 校验状态(关机允许开机)<br>2. 模拟开机逻辑(加载系统)

    %% 4. 关机状态切换手机状态为“开机”
    OffState->>Phone: 4. setCurrentState(OnState.getInstance())
    Note over Phone: currentState 变为 开机状态

    %% 5. 开机结果返回客户端
    OffState-->>Phone: 开机成功
    Phone-->>Client: 手机已开机,当前状态:开机

    %% 6. 用户触发打电话操作
    Client->>Phone: 6. makeCall()
    Note over Phone: 委托当前状态(开机)处理

    %% 7. 手机委托开机状态处理打电话
    Phone->>OnState: 7. handleMakeCall(this)
    Note over OnState: 1. 校验状态(开机允许打电话)<br>2. 模拟拨号逻辑

    %% 8. 开机状态切换手机状态为“通话”
    OnState->>Phone: 8. setCurrentState(CallState.getInstance())
    Note over Phone: currentState 变为 通话状态

    %% 9. 打电话结果返回客户端
    OnState-->>Phone: 通话已接通
    Phone-->>Client: 正在通话中,当前状态:通话

    %% 10. 用户触发挂断操作
    Client->>Phone: 10. endCall()
    Note over Phone: 委托当前状态(通话)处理

    %% 11. 手机委托通话状态处理挂断
    Phone->>CallState: 11. handleEndCall(this)
    Note over CallState: 1. 校验状态(通话允许挂断)<br>2. 模拟挂断逻辑

    %% 12. 通话状态切换手机状态为“开机”
    CallState->>Phone: 12. setCurrentState(OnState.getInstance())
    Note over Phone: currentState 变为 开机状态

    %% 13. 挂断结果返回客户端
    CallState-->>Phone: 通话已挂断
    Phone-->>Client: 通话结束,当前状态:开机

模式分析

1. 核心逻辑:委托与双分派

状态模式的行为触发依赖双分派机制,确保 “不同状态下,同一方法表现不同行为”:

  1. 第一次分派:客户端调用环境类接口(如 Phone.makeCall()),由环境类确定 “当前状态对象”;
  2. 第二次分派:环境类调用当前状态的对应方法(如 currentState.handleMakeCall(this)),由状态对象的实际类型确定具体逻辑。

例如:Phone.makeCall() → 若当前是 OnState,则执行 “开机→通话”;若当前是 CallState,则提示 “通话中不支持重复拨号”。

2. 与策略模式的关键区别

状态模式常与策略模式混淆(两者结构相似),但意图和逻辑完全不同:

对比维度状态模式(State)策略模式(Strategy)
核心意图处理对象的 “状态变化”,行为随状态自动切换封装 “不同算法 / 策略”,由客户端主动选择
状态 / 策略关系状态间存在依赖(如关机→开机→通话)策略间相互独立(如微信支付 / 支付宝支付)
切换主体状态切换由具体状态类控制(内部决定)策略切换由客户端控制(外部决定)
行为约束状态对行为有约束(如关机不能打电话)策略无约束(选任一策略均可完成同一目标)

优点

  1. 消除冗余条件判断:用 “状态类 + 委托” 替代 if-else,代码更简洁、可读性更高,减少 “复制粘贴” 错误;
  2. 符合设计原则:
    • 单一职责:每个状态类仅负责自身的行为和切换逻辑;
    • 开闭原则:新增状态只需添加 ConcreteState 类,无需修改环境类或其他状态类;
  3. 状态逻辑集中:状态的行为和切换规则集中在状态类中,便于调试和维护(如修改 “开机逻辑” 只需改 PoweredOffState);
  4. 行为一致性:所有状态实现同一接口,确保环境类的接口调用稳定(客户端无需关心状态细节)。

缺点

  1. 类数量膨胀:每个状态对应一个类,若状态过多(如 10 + 种),会导致类数量激增(如电商订单有 8 种状态,需 8 个状态类);
  2. 状态耦合增强:具体状态类需知道其他状态类(如 PoweredOffState 需调用 OnState.getInstance()),增加了状态间的依赖;
  3. 学习成本较高:相比直接用 if-else,状态模式的结构更复杂,团队需理解 “委托逻辑” 和 “双分派” 才能正确使用;
  4. 简单场景过度设计:若状态少(仅 2-3 种)且逻辑简单,用状态模式会增加代码复杂度(不如 if-else 直观)。

适用环境

当对象满足以下条件时,适合使用状态模式:

  1. 对象的行为依赖于其内部状态,且状态变化时行为需同步改变(如手机、订单、播放器);
  2. 代码中存在大量与状态相关的条件判断,且判断逻辑重复或嵌套层级深(如 if (stateA) { ... } else if (stateB) { ... } else if (stateC) { ... });
  3. 状态数量明确,且未来可能扩展新状态(如电商订单可能新增 “已退款”“已售后” 状态);
  4. 状态切换规则清晰,且可封装在具体状态类中(如 “关机→开机”“开机→通话” 的规则无歧义)。

模式应用

状态模式在实际开发和框架中应用广泛,典型场景包括:

1. 业务场景

  • 电商领域:订单状态(待支付→已支付→已发货→已签收→已取消)、物流状态(待揽收→运输中→派送中→已签收);
  • 多媒体领域:视频播放器(Idle→Prepared→Playing→Paused→Stopped)、音频 recorder(Idle→Recording→Stopped);
  • 设备控制:电梯(开门→关门→运行→停止)、红绿灯(红灯→绿灯→黄灯)、智能门锁(未上锁→已上锁→临时开锁)。

2. 框架源码

  • Android MediaPlayer:核心组件,生命周期包含 10 种状态(Idle、Initialized、Prepared 等),所有操作(start()/pause())均需校验当前状态,否则抛异常;
  • Spring StateMachine:基于状态模式的状态机框架,支持复杂状态流转(如订单流程、工作流),提供状态持久化、事件驱动等能力;
  • Java Thread.State:线程的 6 种状态(NEW、RUNNABLE、BLOCKED、WAITING、TIMED_WAITING、TERMINATED),但 Thread 未完全遵循状态模式(行为未委托给状态类,仅用枚举标识状态)。

模式扩展

1. 状态管理器(State Manager)

当状态数量较多时,新增 “状态管理器” 统一管理所有状态实例,避免每个 ConcreteState 重复写单例逻辑,同时简化状态获取:

// 手机状态管理器:统一管理所有状态实例
public class PhoneStateManager {
    // 状态池:存储状态标识与实例的映射
    private static final Map<String, PhoneState> STATE_MAP = new HashMap<>();

    // 静态初始化:加载所有状态
    static {
        STATE_MAP.put("POWERED_OFF", PoweredOffState.getInstance());
        STATE_MAP.put("POWERED_ON", PoweredOnState.getInstance());
        STATE_MAP.put("CALLING", CallingState.getInstance());
    }

    // 根据状态标识获取状态实例(如从数据库加载时使用)
    public static PhoneState getState(String stateCode) {
        return STATE_MAP.getOrDefault(stateCode, PoweredOffState.getInstance());
    }
}

2. 状态持久化

在分布式系统中,需将状态持久化到数据库(如手机状态存 phone_state 字段),恢复时通过状态管理器加载对应状态:

// 从数据库加载手机信息时,恢复状态
public Phone loadPhoneFromDB(String phoneId) {
    // 1. 从数据库查询手机信息(phoneId、battery、stateCode)
    String dbStateCode = "POWERED_ON"; // 假设查询结果为“开机”
    int dbBattery = 80; // 假设电量80%

    // 2. 通过状态管理器获取对应状态实例
    PhoneState state = PhoneStateManager.getState(dbStateCode);

    // 3. 构建手机对象并设置状态
    Phone phone = new Phone(phoneId);
    phone.setCurrentState(state);
    phone.setBattery(dbBattery); // 假设Phone有setBattery方法

    return phone;
}

3. 分层状态(Hierarchical State)

当状态存在 “父子关系” 时,可设计分层状态(如 “开机状态” 包含 “待机”“通话”“充电” 子状态),父状态实现公共行为,子状态实现差异化行为:

// 父状态:开机状态(包含子状态)
public class PoweredOnState implements PhoneState {
    // 子状态:待机、通话、充电
    private PhoneState subState;

    @Override
    public void handlePowerOff(phone: Phone) {
        // 父状态公共行为:所有开机子状态均可关机
        phone.setCurrentState(PoweredOffState.getInstance());
    }

    // 子状态差异化行为:委托给子状态处理
    @Override
    public void handleMakeCall(phone: Phone) {
        subState.handleMakeCall(phone);
    }
}

Android 中的应用

Android 框架和开发中,状态模式的思想和实践非常普遍:

1. MediaPlayer 状态管理

MediaPlayer 是 Android 多媒体核心组件,严格遵循状态模式的设计思想:

  • 环境类:MediaPlayer 本身,持有当前状态(如 mState 变量);
  • 抽象状态:无显式接口,但内部通过 mState 变量标识状态(如 STATE_IDLE、STATE_PREPARED);
  • 具体状态:内部通过 checkState() 方法校验状态,不同状态下执行不同行为(如 start() 仅在 STATE_PREPARED/STATE_PAUSED 状态下有效);
  • 行为约束:若在错误状态调用方法(如 STATE_IDLE 调用 start()),会抛出 IllegalStateException,确保状态合法性。

2. View 状态与 StateListDrawable

Android View 的状态(如 Pressed、Focused、Selected)通过 StateListDrawable 管理,本质是状态模式的简化:

  • 环境类:View,持有当前状态(如 mDrawableState 数组);
  • 抽象状态:StateListDrawable 定义状态集合(如 android.R.attr.state_pressed);
  • 具体状态:每个状态对应一个 Drawable(如按下状态对应 pressed_bg,正常状态对应 normal_bg);
  • 行为:View 状态变化时(如用户触摸),StateListDrawable 自动加载对应状态的 Drawable,无需开发者手动切换。

3. Activity 生命周期(类状态模式)

Activity 的生命周期虽由系统回调触发,但思想与状态模式一致:

  • 状态:Created→Started→Resumed→Paused→Stopped→Destroyed;
  • 行为约束:不同状态下执行不同操作(如 onResume() 时界面可见可交互,onPause() 时需暂停耗时操作);
  • 状态切换:由系统控制(如用户按 Home 键触发 onPause()→onStop()),开发者只需在对应回调中实现逻辑,无需手动判断状态。

4. 自定义 View 状态管理

开发自定义 View 时(如自定义按钮、进度条),常需用状态模式管理自定义状态:

// 自定义按钮:支持“加载中”状态
public class LoadingButton extends Button {
    // 自定义状态:加载中
    private boolean isLoading;

    @Override
    protected int[] onCreateDrawableState(int extraSpace) {
        // 1. 扩展状态数组,添加“加载中”状态
        int[] state = super.onCreateDrawableState(extraSpace + 1);
        if (isLoading) {
            mergeDrawableStates(state, new int[]{R.attr.state_loading});
        }
        return state;
    }

    // 切换“加载中”状态
    public void setLoading(boolean loading) {
        isLoading = loading;
        // 2. 状态变化时,刷新View
        refreshDrawableState();
    }
}

// 布局中使用:通过StateListDrawable定义状态对应的背景
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/loading_bg" android:state_loading="true"/>
    <item android:drawable="@drawable/normal_bg" android:state_loading="false"/>
</selector>

代码实现 手机状态管理

基于 “手机状态管理” 场景,完整实现状态模式:

1. 步骤 1:定义抽象状态接口(PhoneState)

// 抽象状态:定义手机行为的统一接口
public interface PhoneState {
    // 处理开机
    void handlePowerOn(Phone phone);
    // 处理关机
    void handlePowerOff(Phone phone);
    // 处理打电话
    void handleMakeCall(Phone phone);
    // 处理挂断电话
    void handleEndCall(Phone phone);
    // 获取状态名称(辅助打印)
    String getStateName();
}

2. 步骤 2:实现具体状态类

关机状态(PoweredOffState)

// 具体状态1:关机状态
public class PoweredOffState implements PhoneState {
    // 单例:避免重复创建状态对象(状态无内部变量,可共享)
    private static final PoweredOffState INSTANCE = new PoweredOffState();

    // 私有构造:防止外部实例化
    private PoweredOffState() {}

    // 全局获取单例
    public static PoweredOffState getInstance() {
        return INSTANCE;
    }

    @Override
    public void handlePowerOn(Phone phone) {
        System.out.println("=== 处理开机操作 ===");
        // 1. 模拟开机逻辑(如加载系统、初始化硬件)
        System.out.println("手机正在开机...");
        // 2. 切换状态为“开机”
        phone.setCurrentState(PoweredOnState.getInstance());
        System.out.println("开机成功!当前状态:" + phone.getCurrentState().getStateName());
    }

    @Override
    public void handlePowerOff(Phone phone) {
        // 关机状态不支持重复关机
        System.err.println("错误:手机当前已关机,无需重复关机!");
    }

    @Override
    public void handleMakeCall(Phone phone) {
        // 关机状态不支持打电话
        System.err.println("错误:手机当前已关机,无法打电话!");
    }

    @Override
    public void handleEndCall(Phone phone) {
        // 关机状态不支持挂断
        System.err.println("错误:手机当前已关机,无通话可挂断!");
    }

    @Override
    public String getStateName() {
        return "关机";
    }
}

开机状态(PoweredOnState)

// 具体状态2:开机状态(待机)
public class PoweredOnState implements PhoneState {
    private static final PoweredOnState INSTANCE = new PoweredOnState();

    private PoweredOnState() {}

    public static PoweredOnState getInstance() {
        return INSTANCE;
    }

    @Override
    public void handlePowerOn(Phone phone) {
        System.err.println("错误:手机当前已开机,无需重复开机!");
    }

    @Override
    public void handlePowerOff(Phone phone) {
        System.out.println("=== 处理关机操作 ===");
        System.out.println("手机正在关机...");
        phone.setCurrentState(PoweredOffState.getInstance());
        System.out.println("关机成功!当前状态:" + phone.getCurrentState().getStateName());
    }

    @Override
    public void handleMakeCall(Phone phone) {
        System.out.println("=== 处理打电话操作 ===");
        System.out.println("正在拨号...");
        // 切换状态为“通话”
        phone.setCurrentState(CallingState.getInstance());
        System.out.println("通话已接通!当前状态:" + phone.getCurrentState().getStateName());
    }

    @Override
    public void handleEndCall(Phone phone) {
        System.err.println("错误:手机当前无通话,无需挂断!");
    }

    @Override
    public String getStateName() {
        return "开机(待机)";
    }
}

通话状态(CallingState)

// 具体状态3:通话状态
public class CallingState implements PhoneState {
    private static final CallingState INSTANCE = new CallingState();

    private CallingState() {}

    public static CallingState getInstance() {
        return INSTANCE;
    }

    @Override
    public void handlePowerOn(Phone phone) {
        System.err.println("错误:手机正在通话中,无法开机!");
    }

    @Override
    public void handlePowerOff(Phone phone) {
        System.err.println("错误:手机正在通话中,无法关机!");
    }

    @Override
    public void handleMakeCall(Phone phone) {
        System.err.println("错误:手机正在通话中,无法重复打电话!");
    }

    @Override
    public void handleEndCall(Phone phone) {
        System.out.println("=== 处理挂断操作 ===");
        System.out.println("正在挂断电话...");
        // 切换状态为“开机(待机)”
        phone.setCurrentState(PoweredOnState.getInstance());
        System.out.println("通话已挂断!当前状态:" + phone.getCurrentState().getStateName());
    }

    @Override
    public String getStateName() {
        return "通话中";
    }
}

3. 步骤 3:实现环境类(Phone)

// 环境类:手机,持有当前状态,委托行为处理
public class Phone {
    private final String phoneId;
    private PhoneState currentState; // 核心:持有当前状态引用
    private int battery = 100; // 默认电量100%

    // 初始化:默认状态为“关机”
    public Phone(String phoneId) {
        this.phoneId = phoneId;
        this.currentState = PoweredOffState.getInstance();
        System.out.println("手机创建成功!" + getPhoneInfo() + ",当前状态:" + currentState.getStateName());
    }

    // 对外接口:开机(委托给当前状态)
    public void powerOn() {
        currentState.handlePowerOn(this);
        // 模拟开机耗电
        battery -= 10;
    }

    // 对外接口:关机(委托给当前状态)
    public void powerOff() {
        currentState.handlePowerOff(this);
    }

    // 对外接口:打电话(委托给当前状态)
    public void makeCall() {
        currentState.handleMakeCall(this);
        // 模拟通话耗电
        battery -= 5;
    }

    // 对外接口:挂断电话(委托给当前状态)
    public void endCall() {
        currentState.handleEndCall(this);
    }

    // 允许状态类修改当前状态(包访问权限,避免外部随意修改)
    void setCurrentState(PhoneState currentState) {
        this.currentState = currentState;
    }

    // 获取当前状态(辅助)
    public PhoneState getCurrentState() {
        return currentState;
    }

    // 获取手机信息(辅助打印)
    public String getPhoneInfo() {
        return "手机ID:" + phoneId + ",电量:" + battery + "%";
    }

    // 设置电量(辅助,如充电逻辑)
    public void setBattery(int battery) {
        this.battery = Math.max(0, Math.min(100, battery));
    }
}

4. 步骤 4:客户端测试

// 客户端:模拟用户操作手机
public class StatePatternTest {
    public static void main(String[] args) {
        // 1. 创建手机(初始状态:关机)
        Phone phone = new Phone("P123456");
        System.out.println("------------------------");

        // 2. 测试1:关机状态下开机
        phone.powerOn();
        System.out.println("当前手机信息:" + phone.getPhoneInfo());
        System.out.println("------------------------");

        // 3. 测试2:开机状态下打电话
        phone.makeCall();
        System.out.println("当前手机信息:" + phone.getPhoneInfo());
        System.out.println("------------------------");

        // 4. 测试3:通话状态下重复打电话(预期失败)
        phone.makeCall();
        System.out.println("------------------------");

        // 5. 测试4:通话状态下挂断
        phone.endCall();
        System.out.println("当前手机信息:" + phone.getPhoneInfo());
        System.out.println("------------------------");

        // 6. 测试5:开机状态下关机
        phone.powerOff();
        System.out.println("------------------------");

        // 7. 测试6:关机状态下打电话(预期失败)
        phone.makeCall();
    }
}

5. 运行结果

手机创建成功!手机ID:P123456,电量:100%,当前状态:关机
------------------------
=== 处理开机操作 ===
手机正在开机...
开机成功!当前状态:开机(待机)
当前手机信息:手机ID:P123456,电量:90%
------------------------
=== 处理打电话操作 ===
正在拨号...
通话已接通!当前状态:通话中
当前手机信息:手机ID:P123456,电量:85%
------------------------
错误:手机正在通话中,无法重复打电话!
------------------------
=== 处理挂断操作 ===
正在挂断电话...
通话已挂断!当前状态:开机(待机)
当前手机信息:手机ID:P123456,电量:85%
------------------------
=== 处理关机操作 ===
手机正在关机...
关机成功!当前状态:关机
------------------------
错误:手机当前已关机,无法打电话!

代码实现 Android 客户端订单状态

以下是一个基于 Android 平台的订单管理实例,结合状态模式与 Android 架构组件(ViewModel、LiveData),实现订单状态的灵活管理与 UI 联动。实例模拟电商 App 中的订单流程,包含状态切换、UI 实时更新、网络请求模拟等核心功能。

功能场景

  • 订单状态:待支付 → 已支付 → 已发货 → 已签收 → 已取消(支持退款场景)
  • 用户操作:支付、取消、查看物流、确认收货、申请退款
  • 自动行为:超时未支付自动取消(模拟)
  • UI 响应:状态变化时自动更新按钮状态、显示对应操作提示

实现架构

├── data
│   ├── model
│   │   ├── Order.java              // 订单数据模型(环境类)
│   │   └── OrderState.java         // 状态接口
│   └── state
│       ├── PendingPayState.java    // 待支付状态
│       ├── PaidState.java          // 已支付状态
│       ├── ShippedState.java       // 已发货状态
│       ├── ReceivedState.java      // 已签收状态
│       └── CancelledState.java     // 已取消状态
├── util
│   └── OrderStateManager.java      // 状态管理器
└── ui
    ├── OrderViewModel.java         // 管理订单数据与状态
    └── OrderActivity.java          // 订单详情页(UI展示)

完整代码实现

1. 订单模型与状态接口

OrderState.java(抽象状态接口)
package com.example.orderdemo.data.model;

import android.content.Context;

/**
 * 抽象状态接口:定义所有订单状态的操作
 */
public interface OrderState {
    // 处理支付
    void handlePay(Order order, Context context);

    // 处理取消订单
    void handleCancel(Order order, Context context);

    // 处理发货(商家操作,客户端仅显示)
    void handleShip(Order order, String logisticsNo);

    // 处理确认收货
    void handleReceive(Order order, Context context);

    // 处理退款
    void handleRefund(Order order, Context context);

    // 获取状态名称(用于UI显示)
    String getStateName();

    // 获取状态编码(用于持久化)
    String getStateCode();

    // 获取当前状态下可用的操作按钮
    int[] getAvailableActions();
}
Order.java(订单模型 - 环境类)
package com.example.orderdemo.data.model;

import android.content.Context;
import android.util.Log;

import androidx.lifecycle.MutableLiveData;

import com.example.orderdemo.util.OrderStateManager;

import java.util.Date;
import java.util.UUID;

/**
 * 订单实体类(环境类)
 */
public class Order {
    private static final String TAG = "Order";
    
    private final String orderId;
    private final String productName;
    private final double price;
    private final Date createTime;
    private String logisticsNo;
    private Date payTime;
    private Date shipTime;
    private Date receiveTime;
    private Date cancelTime;
    private Date refundTime;
    
    // 核心:当前状态(使用LiveData便于UI观察)
    private final MutableLiveData<OrderState> currentState = new MutableLiveData<>();

    public Order(String productName, double price) {
        this.orderId = generateOrderId();
        this.productName = productName;
        this.price = price;
        this.createTime = new Date();
        // 初始状态:待支付
        this.currentState.setValue(OrderStateManager.getPendingPayState());
        Log.d(TAG, "创建新订单: " + orderId);
    }

    // 生成唯一订单ID
    private String generateOrderId() {
        return "ORD" + System.currentTimeMillis() + UUID.randomUUID().toString().substring(0, 6);
    }

    // 对外暴露的操作方法(委托给当前状态)
    public void pay(Context context) {
        OrderState state = currentState.getValue();
        if (state != null) {
            state.handlePay(this, context);
        }
    }

    public void cancel(Context context) {
        OrderState state = currentState.getValue();
        if (state != null) {
            state.handleCancel(this, context);
        }
    }

    public void ship(String logisticsNo) {
        OrderState state = currentState.getValue();
        if (state != null) {
            state.handleShip(this, logisticsNo);
        }
    }

    public void receive(Context context) {
        OrderState state = currentState.getValue();
        if (state != null) {
            state.handleReceive(this, context);
        }
    }

    public void refund(Context context) {
        OrderState state = currentState.getValue();
        if (state != null) {
            state.handleRefund(this, context);
        }
    }

    // 状态切换(由具体状态类调用)
    public void setState(OrderState newState) {
        Log.d(TAG, "订单状态变更: " + currentState.getValue().getStateName() + 
                " -> " + newState.getStateName());
        currentState.setValue(newState);
    }

    // Getters
    public String getOrderId() { return orderId; }
    public String getProductName() { return productName; }
    public double getPrice() { return price; }
    public Date getCreateTime() { return createTime; }
    public String getLogisticsNo() { return logisticsNo; }
    public Date getPayTime() { return payTime; }
    public Date getShipTime() { return shipTime; }
    public Date getReceiveTime() { return receiveTime; }
    public MutableLiveData<OrderState> getCurrentState() { return currentState; }

    // Setters(仅允许状态类设置)
    public void setLogisticsNo(String logisticsNo) { this.logisticsNo = logisticsNo; }
    public void setPayTime(Date payTime) { this.payTime = payTime; }
    public void setShipTime(Date shipTime) { this.shipTime = shipTime; }
    public void setReceiveTime(Date receiveTime) { this.receiveTime = receiveTime; }
    public void setCancelTime(Date cancelTime) { this.cancelTime = cancelTime; }
    public void setRefundTime(Date refundTime) { this.refundTime = refundTime; }
}

2. 具体状态实现

PendingPayState.java(待支付状态)
package com.example.orderdemo.data.state;

import android.content.Context;
import android.widget.Toast;

import com.example.orderdemo.data.model.Order;
import com.example.orderdemo.data.model.OrderState;
import com.example.orderdemo.util.OrderStateManager;

import java.util.Date;

/**
 * 待支付状态
 */
public class PendingPayState implements OrderState {
    // 单例实例
    private static final PendingPayState INSTANCE = new PendingPayState();

    private PendingPayState() {}

    public static PendingPayState getInstance() {
        return INSTANCE;
    }

    @Override
    public void handlePay(Order order, Context context) {
        // 模拟支付流程
        Toast.makeText(context, "正在发起支付...", Toast.LENGTH_SHORT).show();
        
        // 模拟网络请求延迟
        new Thread(() -> {
            try {
                Thread.sleep(1500); // 模拟支付处理时间
                // 支付成功,切换到已支付状态
                order.setPayTime(new Date());
                order.setState(OrderStateManager.getPaidState());
                
                // 在UI线程显示结果
                ((android.app.Activity) context).runOnUiThread(() -> 
                    Toast.makeText(context, "支付成功!", Toast.LENGTH_SHORT).show());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();
    }

    @Override
    public void handleCancel(Order order, Context context) {
        order.setCancelTime(new Date());
        order.setState(OrderStateManager.getCancelledState());
        Toast.makeText(context, "订单已取消", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void handleShip(Order order, String logisticsNo) {
        // 待支付状态不支持发货
    }

    @Override
    public void handleReceive(Order order, Context context) {
        Toast.makeText(context, "请先完成支付", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void handleRefund(Order order, Context context) {
        Toast.makeText(context, "未支付订单无法退款", Toast.LENGTH_SHORT).show();
    }

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

    @Override
    public String getStateCode() {
        return "PENDING_PAY";
    }

    @Override
    public int[] getAvailableActions() {
        // 待支付状态下可用的操作:支付、取消
        return new int[]{Action.PAY, Action.CANCEL};
    }
}
PaidState.java(已支付状态)
package com.example.orderdemo.data.state;

import android.content.Context;
import android.widget.Toast;

import com.example.orderdemo.data.model.Order;
import com.example.orderdemo.data.model.OrderState;
import com.example.orderdemo.util.OrderStateManager;

import java.util.Date;
import java.util.Random;

/**
 * 已支付状态
 */
public class PaidState implements OrderState {
    private static final PaidState INSTANCE = new PaidState();

    private PaidState() {}

    public static PaidState getInstance() {
        return INSTANCE;
    }

    @Override
    public void handlePay(Order order, Context context) {
        Toast.makeText(context, "已完成支付,无需重复支付", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void handleCancel(Order order, Context context) {
        Toast.makeText(context, "已支付订单请申请退款", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void handleShip(Order order, String logisticsNo) {
        // 生成物流单号(模拟商家操作)
        String logNo = logisticsNo != null ? logisticsNo : generateLogisticsNo();
        order.setLogisticsNo(logNo);
        order.setShipTime(new Date());
        order.setState(OrderStateManager.getShippedState());
    }

    @Override
    public void handleReceive(Order order, Context context) {
        Toast.makeText(context, "商家尚未发货,无法确认收货", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void handleRefund(Order order, Context context) {
        Toast.makeText(context, "正在处理退款...", Toast.LENGTH_SHORT).show();
        
        new Thread(() -> {
            try {
                Thread.sleep(2000);
                order.setRefundTime(new Date());
                order.setState(OrderStateManager.getCancelledState());
                
                ((android.app.Activity) context).runOnUiThread(() -> 
                    Toast.makeText(context, "退款成功", Toast.LENGTH_SHORT).show());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();
    }

    // 生成模拟物流单号
    private String generateLogisticsNo() {
        return "SF" + new Random().nextInt(1000000000);
    }

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

    @Override
    public String getStateCode() {
        return "PAID";
    }

    @Override
    public int[] getAvailableActions() {
        // 已支付状态下可用的操作:查看物流(模拟)、申请退款
        return new int[]{Action.VIEW_LOGISTICS, Action.REFUND};
    }
}	

(其他状态类 ShippedState.java、ReceivedState.java、CancelledState.java 实现类似,略)

3. 状态管理器与操作常量

OrderStateManager.java(状态管理器)
package com.example.orderdemo.util;

import com.example.orderdemo.data.model.OrderState;
import com.example.orderdemo.data.state.CancelledState;
import com.example.orderdemo.data.state.PaidState;
import com.example.orderdemo.data.state.PendingPayState;
import com.example.orderdemo.data.state.ReceivedState;
import com.example.orderdemo.data.state.ShippedState;

/**
 * 订单状态管理器:提供统一的状态实例访问
 */
public class OrderStateManager {
    // 所有状态实例
    private static final OrderState PENDING_PAY = PendingPayState.getInstance();
    private static final OrderState PAID = PaidState.getInstance();
    private static final OrderState SHIPPED = ShippedState.getInstance();
    private static final OrderState RECEIVED = ReceivedState.getInstance();
    private static final OrderState CANCELLED = CancelledState.getInstance();

    // 根据状态编码获取状态实例(用于从网络/数据库恢复)
    public static OrderState getStateByCode(String code) {
        switch (code) {
            case "PAID":
                return PAID;
            case "SHIPPED":
                return SHIPPED;
            case "RECEIVED":
                return RECEIVED;
            case "CANCELLED":
                return CANCELLED;
            default: // 默认待支付
                return PENDING_PAY;
        }
    }

    // 直接获取特定状态
    public static OrderState getPendingPayState() { return PENDING_PAY; }
    public static OrderState getPaidState() { return PAID; }
    public static OrderState getShippedState() { return SHIPPED; }
    public static OrderState getReceivedState() { return RECEIVED; }
    public static OrderState getCancelledState() { return CANCELLED; }
}
Action.java(操作常量)
package com.example.orderdemo.data.model;

/**
 * 订单支持的操作类型
 */
public class Action {
    // 操作常量
    public static final int PAY = 1;         // 支付
    public static final int CANCEL = 2;      // 取消
    public static final int VIEW_LOGISTICS = 3; // 查看物流
    public static final int RECEIVE = 4;     // 确认收货
    public static final int REFUND = 5;      // 申请退款

    // 操作名称映射
    public static String getActionName(int action) {
        switch (action) {
            case PAY: return "去支付";
            case CANCEL: return "取消订单";
            case VIEW_LOGISTICS: return "查看物流";
            case RECEIVE: return "确认收货";
            case REFUND: return "申请退款";
            default: return "";
        }
    }
}

4. ViewModel 与 UI 实现

OrderViewModel.java
package com.example.orderdemo.ui;

import android.app.Application;

import androidx.annotation.NonNull;
import androidx.lifecycle.AndroidViewModel;
import androidx.lifecycle.LiveData;

import com.example.orderdemo.data.model.Order;

/**
 * 订单视图模型:管理订单数据,处理业务逻辑
 */
public class OrderViewModel extends AndroidViewModel {
    private Order currentOrder;

    public OrderViewModel(@NonNull Application application) {
        super(application);
        // 模拟创建一个订单
        currentOrder = new Order("无线蓝牙耳机", 299.00);
        
        // 模拟商家发货(实际场景由服务器触发)
        simulateShipAfterDelay();
    }

    // 获取当前订单
    public Order getCurrentOrder() {
        return currentOrder;
    }

    // 模拟支付后一段时间商家发货
    private void simulateShipAfterDelay() {
        new Thread(() -> {
            try {
                Thread.sleep(30000); // 30秒后模拟发货
                if (currentOrder != null && 
                    "PAID".equals(currentOrder.getCurrentState().getValue().getStateCode())) {
                    currentOrder.ship(null); // 自动发货
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();
    }

    // 模拟超时未支付自动取消
    public void startPaymentTimeoutCheck() {
        new Thread(() -> {
            try {
                Thread.sleep(60000); // 60秒后检查
                if (currentOrder != null && 
                    "PENDING_PAY".equals(currentOrder.getCurrentState().getValue().getStateCode())) {
                    currentOrder.cancel(getApplication()); // 自动取消
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();
    }
}
OrderActivity.java
package com.example.orderdemo.ui;

import androidx.appcompat.app.AppCompatActivity;
import androidx.lifecycle.ViewModelProvider;

import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;

import com.example.orderdemo.R;
import com.example.orderdemo.data.model.Action;
import com.example.orderdemo.data.model.Order;
import com.example.orderdemo.data.model.OrderState;

import java.text.SimpleDateFormat;

public class OrderActivity extends AppCompatActivity {
    private OrderViewModel orderViewModel;
    private Order currentOrder;
    private TextView tvOrderId;
    private TextView tvProduct;
    private TextView tvPrice;
    private TextView tvState;
    private TextView tvTime;
    private LinearLayout llActions;
    private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_order);
        
        // 初始化视图
        initViews();
        
        // 获取ViewModel
        orderViewModel = new ViewModelProvider(this).get(OrderViewModel.class);
        currentOrder = orderViewModel.getCurrentOrder();
        updateOrderInfo();
        
        // 观察状态变化
        observeStateChanges();
        
        // 启动支付超时检查
        orderViewModel.startPaymentTimeoutCheck();
    }

    private void initViews() {
        tvOrderId = findViewById(R.id.tv_order_id);
        tvProduct = findViewById(R.id.tv_product);
        tvPrice = findViewById(R.id.tv_price);
        tvState = findViewById(R.id.tv_state);
        tvTime = findViewById(R.id.tv_time);
        llActions = findViewById(R.id.ll_actions);
    }

    private void observeStateChanges() {
        currentOrder.getCurrentState().observe(this, state -> {
            // 状态变化时更新UI
            updateOrderInfo();
            updateActionButtons(state);
        });
    }

    // 更新订单基本信息
    private void updateOrderInfo() {
        tvOrderId.setText("订单编号: " + currentOrder.getOrderId());
        tvProduct.setText("商品: " + currentOrder.getProductName());
        tvPrice.setText("金额: ¥" + currentOrder.getPrice());
        tvState.setText("当前状态: " + currentOrder.getCurrentState().getValue().getStateName());
        tvTime.setText("创建时间: " + sdf.format(currentOrder.getCreateTime()));
    }

    // 根据当前状态更新操作按钮
    private void updateActionButtons(OrderState state) {
        llActions.removeAllViews();
        int[] actions = state.getAvailableActions();
        
        for (int action : actions) {
            Button button = new Button(this);
            button.setText(Action.getActionName(action));
            button.setOnClickListener(v -> handleAction(action));
            
            // 添加按钮到布局
            LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
                    0, LinearLayout.LayoutParams.WRAP_CONTENT, 1);
            params.setMargins(8, 8, 8, 8);
            llActions.addView(button, params);
        }
    }

    // 处理用户操作
    private void handleAction(int action) {
        switch (action) {
            case Action.PAY:
                currentOrder.pay(this);
                break;
            case Action.CANCEL:
                currentOrder.cancel(this);
                break;
            case Action.VIEW_LOGISTICS:
                String logisticsNo = currentOrder.getLogisticsNo();
                if (logisticsNo != null) {
                    Toast.makeText(this, "物流单号: " + logisticsNo, Toast.LENGTH_LONG).show();
                } else {
                    Toast.makeText(this, "商家尚未发货", Toast.LENGTH_SHORT).show();
                }
                break;
            case Action.RECEIVE:
                currentOrder.receive(this);
                break;
            case Action.REFUND:
                currentOrder.refund(this);
                break;
        }
    }
}
activity_order.xml(布局文件)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="16dp">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="订单详情"
        android:textSize="20sp"
        android:textStyle="bold"/>

    <TextView
        android:id="@+id/tv_order_id"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="16dp"
        android:textSize="16sp"/>

    <TextView
        android:id="@+id/tv_product"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="8dp"
        android:textSize="16sp"/>

    <TextView
        android:id="@+id/tv_price"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="8dp"
        android:textColor="@color/design_default_color_error"
        android:textSize="16sp"/>

    <TextView
        android:id="@+id/tv_state"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="8dp"
        android:textSize="16sp"/>

    <TextView
        android:id="@+id/tv_time"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="8dp"
        android:textSize="14sp"
        android:textColor="@android:color/darker_gray"/>

    <LinearLayout
        android:id="@+id/ll_actions"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="32dp"
        android:orientation="horizontal"/>

</LinearLayout>

实现说明

核心设计亮点

  1. 状态与 UI 解耦
    • 使用 LiveData 观察状态变化,状态变更时自动更新 UI
    • 操作按钮根据当前状态动态生成,无需在布局中预先定义所有按钮
  2. 符合 Android 生命周期
    • 订单数据通过 ViewModel 管理,旋转屏幕等配置变化时数据不丢失
    • 耗时操作(如支付、退款)在子线程执行,避免阻塞 UI
  3. 业务逻辑封装
    • 每个状态的行为约束和状态切换逻辑封装在对应状态类中
    • 状态管理器统一管理状态实例,避免重复创建和状态不一致
  4. 可扩展性
    • 新增状态只需实现 OrderState 接口并注册到状态管理器
    • 新增操作只需在 Action 类中添加常量,在对应状态类中实现逻辑

状态流转测试流程

  1. 打开订单详情页,初始状态为 "待支付",显示 "去支付" 和 "取消订单" 按钮
  2. 点击 "去支付",模拟支付成功后状态变为 "已支付"
  3. 30 秒后自动模拟商家发货,状态变为 "已发货"
  4. 点击 "确认收货",状态变为 "已签收"
  5. 点击 "申请退款",状态变为 "已取消"

扩展建议

  1. 集成真实支付 SDK 在 PendingPayState 的 handlePay 方法中集成微信 / 支付宝支付 SDK,实现真实支付流程
  2. 添加网络同步 状态变更时通过 Retrofit 等网络库同步到服务器,确保客户端与服务端状态一致
  3. 完善物流跟踪 在 ShippedState 中添加物流状态查询,通过 API 获取实时物流信息
  4. 添加状态历史记录 订单类中添加状态变更历史列表,记录每次状态变更的时间和操作人
  5. 实现订单列表 扩展 ViewModel 管理多个订单,使用 RecyclerView 展示订单列表,每个订单独立管理自己的状态

这个实例完整展示了状态模式在 Android 客户端的应用,通过合理的架构设计实现了订单状态的灵活管理和 UI 的实时响应,同时保持了代码的可维护性和可扩展性。

总结

状态模式是解决 “状态驱动行为” 问题的优秀方案,其核心是 “用对象封装状态,用委托替代判断”:

  1. 核心价值:
    • 消除冗余 if-else,提升代码可读性和可维护性;
    • 状态与行为强绑定,符合单一职责和开闭原则;
    • 适合状态较多且变化频繁的场景(如订单、播放器)。
  2. 使用建议:
    • 状态少(2-3 种)且逻辑简单时,优先用 if-else(避免过度设计);
    • 状态多且逻辑复杂时,用状态模式(推荐结合单例和状态管理器);
    • 分布式场景需注意状态持久化(如将状态存数据库,恢复时通过状态管理器加载)。
  3. Android 开发启示:
    • 自定义 View 或组件时,可用状态模式管理复杂状态(如加载中、成功、失败);
    • 理解 MediaPlayer 等系统组件的状态逻辑,避免因状态错误导致崩溃;
    • 复杂业务流程(如支付流程)可结合 Spring StateMachine 等框架简化开发。

状态模式不是 “万能药”,需根据业务场景权衡其优缺点,才能写出简洁、健壮的代码。

最近更新:: 2025/10/22 15:36
Contributors: 罗凯文, luokaiwen