惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

GbyAI
GbyAI
Martin Fowler
Martin Fowler
云风的 BLOG
云风的 BLOG
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
T
The Blog of Author Tim Ferriss
大猫的无限游戏
大猫的无限游戏
A
About on SuperTechFans
小众软件
小众软件
博客园_首页
博客园 - 聂微东
罗磊的独立博客
Recent Announcements
Recent Announcements
U
Unit 42
N
Netflix TechBlog - Medium
Blog — PlanetScale
Blog — PlanetScale
阮一峰的网络日志
阮一峰的网络日志
博客园 - 叶小钗
V
V2EX
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
IT之家
IT之家
Stack Overflow Blog
Stack Overflow Blog
博客园 - Franky
D
DataBreaches.Net
Last Week in AI
Last Week in AI

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant
状态模式深度指南:构建可动态切换行为的艺术
架构师小白 · 2026-06-26 · via DEV Community

架构师小白

状态模式深度指南:构建可动态切换行为的艺术

状态模式深度指南:构建可动态切换行为的艺术

概述

状态模式(State Pattern)是一种行为型设计模式,它允许对象在内部状态改变时改变其行为。看起来对象似乎修改了其类。这种模式是解决复杂状态转换逻辑的利器,特别适合用于工作流引擎、游戏开发、订单处理系统等场景。

核心概念

状态模式的核心思想是:将每个状态封装为独立的类,对象的行为取决于其当前状态,而状态之间的转换由状态类自己管理

关键角色

  1. Context(上下文):维护当前状态的实例,负责将请求委托给状态对象处理
  2. State(抽象状态):定义所有具体状态的共同接口
  3. ConcreteState(具体状态):实现各个具体状态的行为,并负责状态转换

为什么需要状态模式?

传统方式的困境

想象一个订单系统,订单有多种状态:待支付、待发货、已发货、已完成、已取消。每个状态下可以执行不同的操作。

// 传统的if-else方式
class Order {
    public void process() {
        if (status.equals("待支付")) {
            // 处理支付逻辑
        } else if (status.equals("待发货")) {
            // 处理发货逻辑
        } else if (status.equals("已发货")) {
            // 处理签收逻辑
        }
        // ... 越来越多的条件判断
    }
}

这种方式的问题:

  • 代码膨胀:每个方法都包含大量if-else
  • 难以维护:新增状态需要修改多个方法
  • 违反开闭原则:无法在不修改现有代码的情况下添加新状态
  • 状态逻辑分散:状态转换规则散落在各处

状态模式的解决方案

状态模式通过将每个状态封装为独立类,让每个状态负责自己的行为和转换逻辑,从而解决上述问题。

实战案例:订单状态管理系统

1. 定义抽象状态接口

public interface OrderState {
    void pay(OrderContext context);
    void ship(OrderContext context);
    void deliver(OrderContext context);
    void cancel(OrderContext context);
    String getStatusName();
}

2. 创建具体状态类

// 待支付状态
public class PendingPaymentState implements OrderState {
    @Override
    public void pay(OrderContext context) {
        System.out.println("订单支付成功!");
        context.setState(new PendingShipmentState());
    }

    @Override
    public void ship(OrderContext context) {
        throw new IllegalStateException("订单未支付,无法发货");
    }

    @Override
    public void deliver(OrderContext context) {
        throw new IllegalStateException("订单未发货,无法签收");
    }

    @Override
    public void cancel(OrderContext context) {
        System.out.println("订单已取消");
        context.setState(new CancelledState());
    }

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

// 待发货状态
public class PendingShipmentState implements OrderState {
    @Override
    public void pay(OrderContext context) {
        throw new IllegalStateException("订单已支付");
    }

    @Override
    public void ship(OrderContext context) {
        System.out.println("商品已发货!");
        context.setState(new ShippedState());
    }

    @Override
    public void deliver(OrderContext context) {
        throw new IllegalStateException("订单未发货");
    }

    @Override
    public void cancel(OrderContext context) {
        System.out.println("取消发货,订单退款中");
        context.setState(new CancelledState());
    }

    @Override
    public String getStatusName() {
        return "待发货";
    }
}

// 已发货状态
public class ShippedState implements OrderState {
    @Override
    public void pay(OrderContext context) {
        throw new IllegalStateException("订单已支付");
    }

    @Override
    public void ship(OrderContext context) {
        throw new IllegalStateException("商品已发货");
    }

    @Override
    public void deliver(OrderContext context) {
        System.out.println("订单已完成!");
        context.setState(new CompletedState());
    }

    @Override
    public void cancel(OrderContext context) {
        throw new IllegalStateException("商品已发出,无法取消");
    }

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

// 已完成状态
public class CompletedState implements OrderState {
    @Override
    public void pay(OrderContext context) {
        throw new IllegalStateException("订单已完成");
    }

    @Override
    public void ship(OrderContext context) {
        throw new IllegalStateException("订单已完成");
    }

    @Override
    public void deliver(OrderContext context) {
        throw new IllegalStateException("订单已完成");
    }

    @Override
    public void cancel(OrderContext context) {
        throw new IllegalStateException("已完成订单无法取消");
    }

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

// 已取消状态
public class CancelledState implements OrderState {
    @Override
    public void pay(OrderContext context) {
        throw new IllegalStateException("订单已取消");
    }

    @Override
    public void ship(OrderContext context) {
        throw new IllegalStateException("订单已取消");
    }

    @Override
    public void deliver(OrderContext context) {
        throw new IllegalStateException("订单已取消");
    }

    @Override
    public void cancel(OrderContext context) {
        throw new IllegalStateException("订单已取消");
    }

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

3. 创建上下文类

public class OrderContext {
    private OrderState state;
    private String orderId;

    public OrderContext(String orderId) {
        this.orderId = orderId;
        this.state = new PendingPaymentState(); // 初始状态
    }

    public void setState(OrderState state) {
        this.state = state;
        System.out.println("订单状态变更为: " + state.getStatusName());
    }

    public OrderState getState() {
        return state;
    }

    // 委托给当前状态处理
    public void pay() {
        state.pay(this);
    }

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

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

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

4. 客户端使用

public class Client {
    public static void main(String[] args) {
        OrderContext order = new OrderContext("ORDER-001");

        order.pay();        // 支付 -> 待发货
        order.ship();       // 发货 -> 已发货
        order.deliver();    // 签收 -> 已完成
    }
}

输出:

订单支付成功!
订单状态变更为: 待发货
商品已发货!
订单状态变更为: 已发货
订单已完成!
订单状态变更为: 已完成

状态模式的优缺点

优点

  1. 单一职责:每个状态类只负责自己的行为和状态转换
  2. 开闭原则:新增状态只需添加新的状态类,不影响现有代码
  3. 消除条件判断:用多态替代大量的if-else
  4. 状态转换明确:状态转换逻辑集中在状态类中,便于管理和调试

缺点

  1. 类数量增加:每个状态都需要一个独立类
  2. 学习曲线:对于新手来说,代码结构需要理解时间
  3. 过度设计:对于简单场景可能过于复杂

状态模式 vs 策略模式

这两个模式结构非常相似,但意图不同:

特性 状态模式 策略模式
意图 对象行为随状态自动改变 算法/策略可替换
参与者 上下文知道状态,状态知道转换 上下文选择策略,策略相互独立
改变时机 状态类内部决定转换 客户端决定使用哪个策略
耦合度 状态类之间有依赖 策略类之间通常独立

简单来说:策略模式是"我不变,但你可以换策略",状态模式是"我变了,所以行为也变"

实际应用场景

  1. 工作流引擎:审批流程、状态流转
  2. 游戏开发:角色状态(站立、跑步、跳跃、攻击)
  3. 订单系统:订单生命周期管理
  4. ATM机:不同状态下的操作行为
  5. 网络协议:TCP连接状态管理

状态机与状态模式

对于更复杂的状态转换,建议引入状态机框架:

// 使用Spring Statemachine
@Configuration
@EnableStateMachine
public class OrderStateMachineConfig extends StateMachineConfigurerAdapter<OrderStates, OrderEvents> {

    @Override
    public void configure(StateMachineStateConfigurer<OrderStates, OrderEvents> states) throws Exception {
        states
            .withStates()
            .initial(OrderStates.PENDING_PAYMENT)
            .states(EnumSet.allOf(OrderStates.class))
            .end(OrderStates.COMPLETED)
            .end(OrderStates.CANCELLED);
    }

    @Override
    public void configure(StateMachineTransitionConfigurer<OrderStates, OrderEvents> transitions) throws Exception {
        transitions
            .withExternal()
                .source(OrderStates.PENDING_PAYMENT)
                .target(OrderStates.PENDING_SHIPMENT)
                .event(OrderEvents.PAY)
            .and()
            .withExternal()
                .source(OrderStates.PENDING_SHIPMENT)
                .target(OrderStates.SHIPPED)
                .event(OrderEvents.SHIP);
    }
}

总结

状态模式是处理复杂状态逻辑的利器,它将状态转换封装到独立的状态类中,使得代码更加清晰、易于维护。当你的系统有以下特征时,考虑使用状态模式:

  • 对象行为依赖其内部状态
  • 状态转换逻辑复杂,包含大量条件判断
  • 需要在不修改现有代码的情况下添加新状态
  • 状态转换需要被明确跟踪和管理

掌握状态模式,让你的代码更具可维护性和扩展性!


参考资源

  • 《设计模式:可复用面向对象软件的基础》
  • Spring Statemachine 官方文档