当前位置: 首页 > news >正文

Java 状态模式 详解

状态模式详解

一、状态模式概述

状态模式(State Pattern)是一种行为型设计模式,它允许一个对象在其内部状态改变时改变它的行为,使对象看起来似乎修改了它的类。

核心特点

  • 状态封装:将每个状态的行为封装到独立的类中
  • 状态转换:对象在不同状态间透明切换
  • 消除条件判断:用多态代替状态条件判断
  • 开闭原则:新增状态无需修改现有代码

二、状态模式的结构

主要角色

  1. Context:上下文,维护当前状态
  2. State:抽象状态,定义状态接口
  3. ConcreteState:具体状态,实现特定状态行为

三、状态模式的实现

1. 基本实现

// 状态接口
public interface State {
    void handle(Context context);
}

// 具体状态A
public class ConcreteStateA implements State {
    public void handle(Context context) {
        System.out.println("处理状态A的行为");
        context.setState(new ConcreteStateB());
    }
}

// 具体状态B
public class ConcreteStateB implements State {
    public void handle(Context context) {
        System.out.println("处理状态B的行为");
        context.setState(new ConcreteStateA());
    }
}

// 上下文类
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);
    }
}

// 使用示例
Context context = new Context(new ConcreteStateA());
context.request(); // 执行状态A的行为,并切换到状态B
context.request(); // 执行状态B的行为,并切换回状态A

2. 更复杂的实现(订单状态)

// 订单状态接口
public interface OrderState {
    void next(Order order);
    void prev(Order order);
    void printStatus();
}

// 新建状态
public class NewState implements OrderState {
    public void next(Order order) {
        order.setState(new PaidState());
    }
    
    public void prev(Order order) {
        System.out.println("订单已在初始状态");
    }
    
    public void printStatus() {
        System.out.println("订单状态:新建");
    }
}

// 已支付状态
public class PaidState implements OrderState {
    public void next(Order order) {
        order.setState(new ShippedState());
    }
    
    public void prev(Order order) {
        order.setState(new NewState());
    }
    
    public void printStatus() {
        System.out.println("订单状态:已支付");
    }
}

// 订单类(上下文)
public class Order {
    private OrderState state;
    
    public Order() {
        this.state = new NewState();
    }
    
    public void setState(OrderState state) {
        this.state = state;
    }
    
    public void nextState() {
        state.next(this);
    }
    
    public void previousState() {
        state.prev(this);
    }
    
    public void printStatus() {
        state.printStatus();
    }
}

四、状态模式的应用场景

1. 电梯状态控制

// 电梯状态接口
public interface ElevatorState {
    void openDoor();
    void closeDoor();
    void run();
    void stop();
}

// 运行状态
public class RunningState implements ElevatorState {
    public void openDoor() {
        System.out.println("电梯运行中不能开门");
    }
    
    public void closeDoor() {
        System.out.println("电梯门已是关闭状态");
    }
    
    public void run() {
        System.out.println("电梯已在运行");
    }
    
    public void stop() {
        System.out.println("电梯停止运行");
    }
}

// 停止状态
public class StoppedState implements ElevatorState {
    public void openDoor() {
        System.out.println("电梯门打开");
    }
    
    public void closeDoor() {
        System.out.println("电梯门关闭");
    }
    
    public void run() {
        System.out.println("电梯开始运行");
    }
    
    public void stop() {
        System.out.println("电梯已是停止状态");
    }
}

2. 游戏角色状态

// 游戏角色状态
public interface CharacterState {
    void attack();
    void defend();
    void move();
}

// 正常状态
public class NormalState implements CharacterState {
    public void attack() {
        System.out.println("造成100%伤害");
    }
    
    public void defend() {
        System.out.println("受到100%伤害");
    }
    
    public void move() {
        System.out.println("移动速度100%");
    }
}

// 中毒状态
public class PoisonedState implements CharacterState {
    public void attack() {
        System.out.println("造成80%伤害");
    }
    
    public void defend() {
        System.out.println("受到120%伤害");
    }
    
    public void move() {
        System.out.println("移动速度60%");
    }
}

3. TCP连接状态

// TCP状态接口
public interface TCPState {
    void open();
    void close();
    void acknowledge();
}

// 已建立连接状态
public class EstablishedState implements TCPState {
    public void open() {
        System.out.println("连接已建立,无需再次打开");
    }
    
    public void close() {
        System.out.println("关闭TCP连接");
    }
    
    public void acknowledge() {
        System.out.println("发送ACK响应");
    }
}

// 监听状态
public class ListenState implements TCPState {
    public void open() {
        System.out.println("建立TCP连接");
    }
    
    public void close() {
        System.out.println("未建立连接,无需关闭");
    }
    
    public void acknowledge() {
        System.out.println("未建立连接,不能发送ACK");
    }
}

五、状态模式的变体

1. 状态表驱动

public class StateMachine {
    private Map<State, Map<Event, State>> transitions = new HashMap<>();
    private State currentState;
    
    public void addTransition(State source, Event event, State target) {
        transitions.computeIfAbsent(source, k -> new HashMap<>())
                  .put(event, target);
    }
    
    public void handleEvent(Event event) {
        currentState = transitions.get(currentState).get(event);
    }
}

2. 状态模式与策略模式结合

public class Context {
    private StateStrategy state;
    
    public void setState(StateStrategy state) {
        this.state = state;
    }
    
    public void execute() {
        state.execute();
        state = state.nextState();
    }
}

public interface StateStrategy {
    void execute();
    StateStrategy nextState();
}

六、状态模式的优缺点

优点

  1. 单一职责:每个状态一个类
  2. 开闭原则:易于新增状态
  3. 简化上下文:消除大量条件判断
  4. 状态转换显式:状态转换逻辑清晰

缺点

  1. 类数量多:状态多时代码量大
  2. 过度设计:简单状态机可能不适用
  3. 状态共享:状态间共享数据较复杂

七、最佳实践

  1. 合理划分状态:避免状态粒度过细
  2. 共享状态对象:无状态的状态对象可共享
  3. 状态转换控制:集中或分散管理转换逻辑
  4. 结合其他模式:如与策略模式结合
  5. 文档化状态图:维护状态转换关系图

八、总结

状态模式是管理对象状态的有效方案,特别适用于:

  • 对象行为随状态改变而改变
  • 需要消除大量状态条件判断
  • 状态转换逻辑复杂
  • 需要清晰的状态管理

在实际开发中,状态模式常见于:

  • 工作流引擎
  • 游戏角色状态
  • 设备控制(如电梯、自动售货机)
  • 网络协议实现
  • 订单生命周期管理

正确使用状态模式可以创建清晰、可维护的状态管理代码,但需要注意避免过度设计简单场景。

http://www.dtcms.com/a/111926.html

相关文章:

  • 金融机构开源软件生命周期管理实务
  • 模组COF受损制程排查验证及改善
  • 从文本到多模态:如何将RAG扩展为支持图像+文本检索的增强生成系统?
  • 基于 docker 的 Xinference 全流程部署指南
  • shell语言替换脚本、填补整个命令行
  • 知识考量码【蓝桥】
  • leetcode-代码随想录-链表-翻转链表
  • 框架PasteForm实际开发案例,换个口味显示数据,支持echarts,只需要标记几个特性即可在管理端显示(2)
  • Python办公自动化(2)对wordpdf的操作
  • 青少年编程与数学 02-015 大学数学知识点 04课题、微积分
  • 如何判断多个点组成的3维面不是平的,如果不是平的,如何拆分成多个平面
  • 二叉树 递归
  • Linux操作系统 4.Linux实用操作
  • 《新疆建筑安全员C证》考试信息
  • ttkbootstrap 实现日期选择器, 开始和结束时间
  • OrangePi5Plus开发板不能正确识别USB 3.0 设备 (绿联HUB和Camera)
  • Flutter性能优化细节
  • 分子生成的深层次层次变分自编码器 - DrugHIVE 测评
  • Jetpack Compose CompositionLocal 深入解析:局部参数透传实践
  • Linux信号处理解析:从入门到实战
  • 星途(3)
  • C/C++的条件编译
  • 【Tauri2】014——简单使用listen和emit
  • DuckDB系列教程:如何分析Parquet文件
  • Linux中的调试器gdb与冯·诺伊曼体系
  • 使用MCP方案与Claude实现虚幻引擎自动化游戏开发
  • [2008][note]腔内级联拉曼发射的,二极管泵浦多频调Q laser——
  • 【LLM】使用MySQL MCP Server让大模型轻松操作本地数据库
  • JSON-lib考古现场:在2025年打开赛博古董店的奇妙冒险
  • 如何分析 jstat 统计来定位 GC?