行为型设计模式——状态模式

状态模式(State Pattern) 是一种行为设计模式,将状态封装为独立的类,并将动作委托给代表当前状态的对象。允许对象在其内部状态改变时改变其行为。

特点

1、将状态相关的行为封装在不同的状态类中;2、上下文对象(Context)的行为会随着其状态的改变而改变;2、消除了复杂的条件判断语句,使代码更易于维护和扩展

结构

状态模式结构包括三个部分:

  1. Context(上下文)

    • 维护一个ConcreteState子类的实例,定义当前状态

    • 提供客户端调用的接口,将请求委托给当前状态对象处理

  2. State(状态接口)

    • 定义状态行为的接口

    • 封装与Context特定状态相关的行为

  3. ConcreteState(具体状态)

    • 实现State接口

    • 实现与Context某个状态相关的行为

UML对象图如下:

代码示例

java 复制代码
// 1. 状态接口
interface OrderState {
    // 订单处理
    void process(OrderContext order);
    // 订单取消
    void cancel(OrderContext order);
    // 订单发货
    void ship(OrderContext order);
    // 订单送达
    void deliver(OrderContext order);
    String getStateName();
}

// 2. 抽象状态类(提供默认实现)
abstract class AbstractOrderState implements OrderState {
    @Override
    public void process(OrderContext order) {
        throw new UnsupportedOperationException("当前状态不支持此操作");
    }
    
    @Override
    public void cancel(OrderContext order) {
        throw new UnsupportedOperationException("当前状态不支持此操作");
    }
    
    @Override
    public void ship(OrderContext order) {
        throw new UnsupportedOperationException("当前状态不支持此操作");
    }
    
    @Override
    public void deliver(OrderContext order) {
        throw new UnsupportedOperationException("当前状态不支持此操作");
    }
}

// 3. 具体状态类
class NewOrderState extends AbstractOrderState {
    @Override
    public void process(OrderContext order) {
        System.out.println("处理新订单...");
        order.setState(new ProcessingOrderState());
    }
    
    @Override
    public void cancel(OrderContext order) {
        System.out.println("取消新订单");
        order.setState(new CancelledOrderState());
    }
    
    @Override
    public String getStateName() {
        return "新订单";
    }
}

class ProcessingOrderState extends AbstractOrderState {
    @Override
    public void ship(OrderContext order) {
        System.out.println("订单已发货");
        order.setState(new ShippedOrderState());
    }
    
    @Override
    public void cancel(OrderContext order) {
        System.out.println("取消处理中的订单");
        order.setState(new CancelledOrderState());
    }
    
    @Override
    public String getStateName() {
        return "处理中";
    }
}

class ShippedOrderState extends AbstractOrderState {
    @Override
    public void deliver(OrderContext order) {
        System.out.println("订单已送达");
        order.setState(new DeliveredOrderState());
    }
    
    @Override
    public String getStateName() {
        return "已发货";
    }
}

class DeliveredOrderState extends AbstractOrderState {
    @Override
    public String getStateName() {
        return "已送达";
    }
}

class CancelledOrderState extends AbstractOrderState {
    @Override
    public String getStateName() {
        return "已取消";
    }
}

// 4. 上下文类
class OrderContext {
    private OrderState currentState;
    private String orderId;
    
    public OrderContext(String orderId) {
        this.orderId = orderId;
        this.currentState = new NewOrderState();
    }
    
    public void setState(OrderState state) {
        this.currentState = state;
        System.out.println("订单 [" + orderId + "] 状态变更为: " + state.getStateName());
    }
    
    public void process() {
        currentState.process(this);
    }
    
    public void cancel() {
        currentState.cancel(this);
    }
    
    public void ship() {
        currentState.ship(this);
    }
    
    public void deliver() {
        currentState.deliver(this);
    }
    
    public String getCurrentState() {
        return currentState.getStateName();
    }
}

// 5. 客户端代码
public class OrderStateDemo {
    public static void main(String[] args) {
        OrderContext order = new OrderContext("ORD001");
        System.out.println("初始状态: " + order.getCurrentState());
        
        try {
            order.process();    // 新订单 -> 处理中
            order.ship();       // 处理中 -> 已发货
            order.deliver();    // 已发货 -> 已送达
            
            // 尝试非法操作
            System.out.println("\n尝试取消已送达的订单:");
            order.cancel();     // 应该抛出异常
        } catch (Exception e) {
            System.out.println("操作失败: " + e.getMessage());
        }
        
        System.out.println("\n=== 另一个订单 ===");
        OrderContext order2 = new OrderContext("ORD002");
        order2.cancel();  // 新订单 -> 已取消
    }
}

适合场景

  1. 对象行为依赖于状态 :一个对象的行为取决于它的状态,在运行时根据状态改变行为

  2. 大量条件判断:操作中含有庞大的多分支条件语句,且这些分支依赖于对象的状态

  3. 状态转换复杂:状态转换逻辑复杂或状态数量较多

  4. 需要维护状态历史:需要跟踪状态变化历史

应用案例

  1. 工作流引擎:文档审批流程、订单处理流程

  2. 游戏开发:角色状态(站立、行走、奔跑、跳跃、攻击)

  3. 网络连接:连接状态(建立连接、已连接、断开连接、重新连接)

  4. UI组件:按钮状态(正常、悬停、按下、禁用)

  5. 电梯控制:电梯运行状态(停止、上行、下行、故障)

  6. 自动售货机:商品选择、付款、出货等状态

  7. 线程状态管理:新建、就绪、运行、阻塞、终止

优缺点

优点:

1、单一职责原则 :将与特定状态相关的代码组织到独立的类中;2、开闭原则 :增加新状态时无需修改现有状态类或上下文;3、消除条件语句 :减少上下文中复杂的条件判断;4、状态转换显式化 :使状态转换更加明确;5、提高可维护性:状态逻辑局部化,易于理解和维护

缺点:

1、类数量增加 :每个状态都需要一个对应的类,可能导致类数量膨胀;2、过度设计 :如果状态数量很少或状态转换简单,使用状态模式可能增加复杂性;3、状态共享:不同上下文之间共享状态对象时需要确保线程安全

相关推荐
虹科网络安全21 分钟前
艾体宝干货|数据复制详解:类型、原理与适用场景
java·开发语言·数据库
axng pmje1 小时前
Java语法进阶
java·开发语言·jvm
uzong1 小时前
9 种 RAG 架构,每位 AI 开发者必学:完整实战指南
后端
HackTorjan1 小时前
深度神经网络的反向传播与梯度优化原理
人工智能·spring boot·神经网络·机器学习·dnn
rKWP8gKv71 小时前
Java微服务性能监控:Prometheus与Grafana集成方案
java·微服务·prometheus
老前端的功夫1 小时前
【Java从入门到入土】28:Stream API:告别for循环的新时代
java·开发语言·python
qq_435287921 小时前
第9章 夸父逐日与后羿射日:死循环与进程终止?十个太阳同时值班的并行冲突
java·开发语言·git·死循环·进程终止·并行冲突·夸父逐日
小江的记录本1 小时前
【Kafka核心】架构模型:Producer、Broker、Consumer、Consumer Group、Topic、Partition、Replica
java·数据库·分布式·后端·搜索引擎·架构·kafka
止语Lab1 小时前
从手动到框架:Go DI 演进的三个拐点
开发语言·后端·golang
yaoxin5211231 小时前
397. Java 文件操作基础 - 创建常规文件与临时文件
java·开发语言·python