本文目录导读:

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