深入理解设计模式之状态模式

下面是一篇关于设计模式之状态模式(State Pattern)的详细博客,并附有 Java 实现代码示例。


深入理解设计模式之:状态模式(State Pattern)

一、什么是状态模式?

状态模式(State Pattern)是一种行为型设计模式。它允许一个对象在其内部状态发生改变时,改变其行为(即表现出不同的行为)。状态模式将与状态相关的行为封装到独立的状态类中,并通过状态切换来改变对象的行为。

核心思想:

将状态的切换和行为的变化解耦,使得状态切换变得灵活,代码结构清晰,易于扩展和维护。


二、状态模式的应用场景

  • 对象的行为依赖于它的状态,并且在运行时根据状态发生改变
  • 代码中包含大量与状态相关的条件语句(如 if-else 或 switch-case)
  • 状态切换频繁,且状态行为复杂

常见例子:

  • 工作流引擎(如订单状态:待支付、已支付、已发货、已完成等)
  • TCP 连接状态(CLOSED、LISTEN、SYN_SENT、ESTABLISHED 等)
  • 游戏角色状态(待机、攻击、防御、死亡等)

三、状态模式的结构

  • Context(环境类):持有当前状态对象,负责状态切换
  • State(抽象状态):定义所有具体状态的公共接口
  • ConcreteState(具体状态):实现具体状态对应的行为

四、UML 类图

复制代码
+----------------+        +---------------------+
|    Context     |<>----->|     State           |
+----------------+        +---------------------+
| state: State   |        | + handle()          |
| + setState()   |        +---------------------+
| + request()    |                /_\
+----------------+                 |
                                   |
                +------------------+------------------+
                |                                     |
      +---------------------+             +---------------------+
      | ConcreteStateA      |             | ConcreteStateB      |
      +---------------------+             +---------------------+
      | + handle()          |             | + handle()          |
      +---------------------+             +---------------------+

五、Java 实现代码示例

1. 抽象状态接口

java 复制代码
public interface State {
    void handle(Context context);
}

2. 具体状态类

java 复制代码
public class StateA implements State {
    @Override
    public void handle(Context context) {
        System.out.println("当前状态:A,切换到状态B");
        context.setState(new StateB());
    }
}

public class StateB implements State {
    @Override
    public void handle(Context context) {
        System.out.println("当前状态:B,切换到状态A");
        context.setState(new StateA());
    }
}

3. 环境类

java 复制代码
public class Context {
    private State state;

    public Context(State state) {
        this.state = state;
    }

    public void setState(State state) {
        this.state = state;
    }

    public void request() {
        state.handle(this);
    }
}

4. 客户端调用

java 复制代码
public class Main {
    public static void main(String[] args) {
        Context context = new Context(new StateA());
        context.request(); // 输出:当前状态:A,切换到状态B
        context.request(); // 输出:当前状态:B,切换到状态A
        context.request(); // 输出:当前状态:A,切换到状态B
    }
}

六、实际应用案例:订单状态流转

以电商订单为例,订单有"待支付"、"已支付"、"已发货"、"已完成"四种状态,每种状态下允许的操作不同。

1. 状态接口

java 复制代码
public interface OrderState {
    void next(OrderContext ctx);
    void prev(OrderContext ctx);
    String getStatus();
}

2. 具体状态类

java 复制代码
public class PendingState implements OrderState {
    public void next(OrderContext ctx) {
        ctx.setState(new PaidState());
    }
    public void prev(OrderContext ctx) {
        System.out.println("已是初始状态,不能回退");
    }
    public String getStatus() {
        return "待支付";
    }
}

public class PaidState implements OrderState {
    public void next(OrderContext ctx) {
        ctx.setState(new ShippedState());
    }
    public void prev(OrderContext ctx) {
        ctx.setState(new PendingState());
    }
    public String getStatus() {
        return "已支付";
    }
}

public class ShippedState implements OrderState {
    public void next(OrderContext ctx) {
        ctx.setState(new CompletedState());
    }
    public void prev(OrderContext ctx) {
        ctx.setState(new PaidState());
    }
    public String getStatus() {
        return "已发货";
    }
}

public class CompletedState implements OrderState {
    public void next(OrderContext ctx) {
        System.out.println("订单已完成,不能再前进");
    }
    public void prev(OrderContext ctx) {
        ctx.setState(new ShippedState());
    }
    public String getStatus() {
        return "已完成";
    }
}

3. 环境类

java 复制代码
public class OrderContext {
    private OrderState state;

    public OrderContext() {
        state = new PendingState();
    }

    public void setState(OrderState state) {
        this.state = state;
    }

    public void next() {
        state.next(this);
    }

    public void prev() {
        state.prev(this);
    }

    public void printStatus() {
        System.out.println("当前订单状态:" + state.getStatus());
    }
}

4. 客户端调用

java 复制代码
public class Main {
    public static void main(String[] args) {
        OrderContext order = new OrderContext();
        order.printStatus(); // 待支付
        order.next();
        order.printStatus(); // 已支付
        order.next();
        order.printStatus(); // 已发货
        order.next();
        order.printStatus(); // 已完成
        order.next();        // 订单已完成,不能再前进
        order.prev();
        order.printStatus(); // 已发货
    }
}

七、状态模式的优缺点

优点:

  • 状态切换逻辑清晰,易于扩展和维护
  • 避免大量 if-else 或 switch-case
  • 状态行为封装,符合开闭原则

缺点:

  • 状态类数量可能增多
  • 结构相对复杂

八、总结

状态模式是处理对象状态切换和行为变化的经典方案,广泛应用于工作流、状态机、游戏开发等场景。掌握状态模式有助于编写灵活、可扩展的代码结构。

建议:

  • 当对象行为依赖于状态且状态切换复杂时,优先考虑状态模式
  • 状态模式与策略模式、命令模式等常结合使用

如需更多设计模式讲解或源码分析,欢迎留言交流!

相关推荐
鸽鸽程序猿18 小时前
【项目】【在线判题系统】竞赛发布与撤销发布
状态模式
高晶18 小时前
CANopen 在 BMS 系统中的 C 语言实战指南
设计模式·程序员
博风19 小时前
13、设计模式应用举例:工厂方法模式:创建药品对象
设计模式·工厂方法模式
lemon_sjdk21 小时前
从一段真实的 Electron IM 前端代码,看高级前端的工程化修养
前端·electron·状态模式·im
代钦塔拉21 小时前
【C++/Qt 进阶】设计模式系列(5):适配器模式——给“不兼容的接口“贴一层翻译膜
c++·qt·设计模式
Nebula_g1 天前
云禾外卖补充—项目整体后端运行逻辑-对流程的更深层次理解
java·开发语言·网络·数据库·状态模式·javase
Wang's Blog1 天前
Java 项目实战: 交友项目:登录链路回顾与今日任务地图
java·开发语言·状态模式·交友
Java后端的Ai之路1 天前
14、ReactJS - 路由(Router)
前端·react.js·状态模式
星恒随风1 天前
Linux线程概念详解:从分页存储、页表、MMU与TLB,深入理解线程和进程的区别与联系
linux·运维·笔记·学习·状态模式
bigbread2 天前
策略模式 + 工厂方法模式在项目中的实战应用
设计模式