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

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

相关推荐
a程序小傲2 小时前
京东Java面试被问:基于Gossip协议的最终一致性实现和收敛时间
java·开发语言·前端·数据库·python·面试·状态模式
编程彩机2 小时前
互联网大厂Java面试:从分布式事务到微服务架构场景应用
spring boot·分布式事务·微服务架构·java面试·电商场景
组合缺一2 小时前
MCP 进化:让静态 Tool 进化为具备“上下文感知”的远程 Skills
java·ai·llm·agent·mcp·skills
程序员小白条2 小时前
面试 Java 基础八股文十问十答第二十二期
java·开发语言·数据库·面试·职场和发展·毕设
taihexuelang2 小时前
jenkins 部署java项目
java·servlet·jenkins
手握风云-2 小时前
JavaEE 进阶第十二期:Spring Ioc & DI,从会用容器到成为容器(上)
java·spring·java-ee
2 小时前
java关于键盘录入
java·开发语言
马猴烧酒.2 小时前
JAVA后端对象存储( 图片分享平台)详解
java·开发语言·spring·腾讯云
梅梅绵绵冰2 小时前
springboot初步2
java·spring boot·后端