如何通过一个模拟电梯运行的案例理解Java的状态设计模式

wen java案例 45

本文目录导读:

如何通过一个模拟电梯运行的案例理解Java的状态设计模式

  1. 问题背景
  2. 状态设计模式的核心思想
  3. 电梯模拟案例
  4. 状态转换图
  5. 优势分析
  6. 实际应用场景

我来通过一个电梯运行的模拟案例,详细解释Java中的状态设计模式(State Pattern)。

问题背景

电梯有多种状态:停止、运行、开门、关门、维修等,不同状态下,相同的操作(如按楼层、开门、关门)会产生不同的行为,如果用if-else处理,代码会变得非常复杂且难以维护。

状态设计模式的核心思想

  • 将每个状态封装成独立的类
  • 每个状态类负责该状态下的行为逻辑
  • 通过状态转换来改变对象的行为

电梯模拟案例

1 定义电梯状态接口

public interface ElevatorState {
    // 开门
    void openDoor(Elevator elevator);
    // 关门
    void closeDoor(Elevator elevator);
    // 运行
    void run(Elevator elevator);
    // 停止
    void stop(Elevator elevator);
    // 获取当前状态名称
    String getStateName();
}

2 实现具体状态类

// 停止状态
public class StoppedState implements ElevatorState {
    @Override
    public void openDoor(Elevator elevator) {
        System.out.println("电梯已停止,正在开门...");
        elevator.setState(new DoorOpenState());
    }
    @Override
    public void closeDoor(Elevator elevator) {
        System.out.println("电梯已停止,门已关闭,无需重复关门");
    }
    @Override
    public void run(Elevator elevator) {
        System.out.println("电梯从停止状态开始运行...");
        elevator.setState(new RunningState());
    }
    @Override
    public void stop(Elevator elevator) {
        System.out.println("电梯已经处于停止状态");
    }
    @Override
    public String getStateName() {
        return "停止";
    }
}
// 运行状态
public class RunningState implements ElevatorState {
    @Override
    public void openDoor(Elevator elevator) {
        System.out.println("危险!运行中不能开门!");
    }
    @Override
    public void closeDoor(Elevator elevator) {
        System.out.println("运行中,门已关闭");
    }
    @Override
    public void run(Elevator elevator) {
        System.out.println("电梯正在运行中...");
    }
    @Override
    public void stop(Elevator elevator) {
        System.out.println("电梯正在减速停止...");
        elevator.setState(new StoppedState());
    }
    @Override
    public String getStateName() {
        return "运行中";
    }
}
// 开门状态
public class DoorOpenState implements ElevatorState {
    @Override
    public void openDoor(Elevator elevator) {
        System.out.println("门已经打开");
    }
    @Override
    public void closeDoor(Elevator elevator) {
        System.out.println("正在关闭电梯门...");
        elevator.setState(new StoppedState());
    }
    @Override
    public void run(Elevator elevator) {
        System.out.println("门未关闭,不能运行!请先关门");
    }
    @Override
    public void stop(Elevator elevator) {
        System.out.println("电梯已经停止,门是打开的");
    }
    @Override
    public String getStateName() {
        return "开门";
    }
}
// 维修状态
public class MaintenanceState implements ElevatorState {
    @Override
    public void openDoor(Elevator elevator) {
        System.out.println("维修中,无法开门");
    }
    @Override
    public void closeDoor(Elevator elevator) {
        System.out.println("维修中,门已锁定");
    }
    @Override
    public void run(Elevator elevator) {
        System.out.println("维修中,电梯无法运行");
    }
    @Override
    public void stop(Elevator elevator) {
        System.out.println("维修中,电梯已停止");
    }
    @Override
    public String getStateName() {
        return "维修中";
    }
}

3 创建电梯上下文类

public class Elevator {
    private ElevatorState currentState;
    private int currentFloor;
    public Elevator() {
        // 初始状态为停止
        this.currentState = new StoppedState();
        this.currentFloor = 1;
    }
    public void setState(ElevatorState state) {
        this.currentState = state;
        System.out.println("状态转换: " + currentState.getStateName());
    }
    public ElevatorState getState() {
        return currentState;
    }
    // 委托给当前状态处理
    public void openDoor() {
        currentState.openDoor(this);
    }
    public void closeDoor() {
        currentState.closeDoor(this);
    }
    public void run() {
        currentState.run(this);
    }
    public void stop() {
        currentState.stop(this);
    }
    public void showStatus() {
        System.out.println("当前楼层: " + currentFloor + 
                          ", 状态: " + currentState.getStateName());
    }
}

4 测试代码

public class ElevatorDemo {
    public static void main(String[] args) {
        Elevator elevator = new Elevator();
        System.out.println("=== 电梯初始状态 ===");
        elevator.showStatus();
        System.out.println("\n=== 测试运行流程 ===");
        elevator.run();     // 停止 -> 运行
        elevator.stop();    // 运行 -> 停止
        elevator.openDoor(); // 停止 -> 开门
        elevator.closeDoor(); // 开门 -> 停止
        System.out.println("\n=== 测试错误操作 ===");
        elevator.openDoor();
        elevator.run();     // 停止 -> 运行
        elevator.openDoor(); // 运行中不能开门(提示错误)
        System.out.println("\n=== 测试维修状态 ===");
        elevator.stop();
        elevator.setState(new MaintenanceState());
        elevator.openDoor(); // 维修中无法开门
        elevator.run();     // 维修中无法运行
    }
}

状态转换图

         ┌──────────┐
         │  停止状态  │
         └────┬─────┘
              │
     ┌────────┼────────┐
     │        │        │
     ▼        ▼        ▼
  ┌──────┐ ┌──────┐ ┌──────┐
  │ 开门  │ │ 运行  │ │ 维修  │
  └──┬───┘ └──┬───┘ └──────┘
     │        │
     └────────┘
         │
         ▼
      ┌──────┐
      │ 停止  │ (闭环)
      └──────┘

优势分析

1 代码清晰

  • 每个状态的行为集中在对应的类中
  • 消除了大量的if-else判断
  • 新增状态只需添加新类,符合开闭原则

2 易于维护

  • 修改某个状态的行为只需修改对应的状态类
  • 状态转换逻辑清晰可见
  • 便于单元测试

3 安全性

  • 非法操作在状态内部被拦截
  • 避免了运行时错误

实际应用场景

状态设计模式适用于:

  • 工作流引擎:审批流程的状态管理
  • 游戏开发:角色状态(行走、攻击、防御)
  • 订单系统:订单状态管理(已下单、已付款、已发货)
  • 通信协议:TCP连接的状态管理

通过电梯模拟案例,我们可以看到状态设计模式如何优雅地处理复杂的状态转换逻辑,它将每个状态封装成独立的类,使得代码更加模块化、可维护性更强,当对象的行为依赖于其状态,且状态转换逻辑复杂时,状态模式是一个非常合适的选择。

抱歉,评论功能暂时关闭!