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

状态模式(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、状态共享:不同上下文之间共享状态对象时需要确保线程安全

相关推荐
SmartBrain7 分钟前
Spring Boot 中常用注解总结(AI工程化)
java·人工智能·spring boot·后端
爱丽_11 分钟前
AQS 原理主线:state、CLH 队列、独占/共享与实战排查
java·开发语言·jvm
小江的记录本18 分钟前
【Redis】Redis常用命令速查表(完整版)
java·前端·数据库·redis·后端·spring·缓存
卓怡学长18 分钟前
m281基于SSM框架的电脑测评系统
java·数据库·spring·tomcat·maven·intellij-idea
umeelove3521 分钟前
SQL中的DISTINCT、SQL DISTINCT详解、DISTINCT的用法、DISTINCT注意事项
java·数据库·sql
AMoon丶22 分钟前
Golang--垃圾回收
java·linux·开发语言·jvm·后端·算法·golang
填满你的记忆22 分钟前
RAG 架构在实际项目中的应用(从原理到落地)
java·ai·架构
Densen201425 分钟前
企业H5站点升级PWA (二)
java·后端·spring
Aaa1111144327 分钟前
限流算法 限流算法
java·开发语言
用户21903265273533 分钟前
部署OpenClaw整合QQ机器人
后端