Java状态模式实现案例
状态模式(State Pattern)允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类。

基础案例:订单状态
// 订单状态接口
public interface OrderState {
void process(OrderContext context);
void cancel(OrderContext context);
void pay(OrderContext context);
String getStateName();
}
// 订单上下文
public class OrderContext {
private OrderState currentState;
private String orderId;
public OrderContext(String orderId) {
this.orderId = orderId;
this.currentState = new NewOrderState(); // 初始状态为新建订单
}
public void process() {
currentState.process(this);
}
public void cancel() {
currentState.cancel(this);
}
public void pay() {
currentState.pay(this);
}
public void setState(OrderState state) {
System.out.println("订单 " + orderId + " 状态变更: "
+ currentState.getStateName() + " -> " + state.getStateName());
this.currentState = state;
}
public OrderState getState() {
return currentState;
}
}
// 新建订单状态
class NewOrderState implements OrderState {
@Override
public void process(OrderContext context) {
System.out.println("订单已确认,进入处理流程");
context.setState(new ProcessingOrderState());
}
@Override
public void cancel(OrderContext context) {
System.out.println("新建订单取消成功");
context.setState(new CancelledOrderState());
}
@Override
public void pay(OrderContext context) {
System.out.println("新建订单支付成功");
context.setState(new PaidOrderState());
}
@Override
public String getStateName() {
return "新建订单";
}
}
// 处理中订单状态
class ProcessingOrderState implements OrderState {
@Override
public void process(OrderContext context) {
System.out.println("订单正在处理中,不能重复处理");
}
@Override
public void cancel(OrderContext context) {
System.out.println("处理中的订单取消成功");
context.setState(new CancelledOrderState());
}
@Override
public void pay(OrderContext context) {
System.out.println("订单已支付完成");
context.setState(new PaidOrderState());
}
@Override
public String getStateName() {
return "处理中";
}
}
// 已支付订单状态
class PaidOrderState implements OrderState {
@Override
public void process(OrderContext context) {
System.out.println("已支付订单不能再次处理");
}
@Override
public void cancel(OrderContext context) {
System.out.println("已支付订单取消,开始退款流程");
context.setState(new RefundProcessingState());
}
@Override
public void pay(OrderContext context) {
System.out.println("订单已支付,不能重复支付");
}
@Override
public String getStateName() {
return "已支付";
}
}
// 取消订单状态
class CancelledOrderState implements OrderState {
@Override
public void process(OrderContext context) {
System.out.println("已取消的订单不能处理");
}
@Override
public void cancel(OrderContext context) {
System.out.println("订单已经取消");
}
@Override
public void pay(OrderContext context) {
System.out.println("已取消的订单不能支付");
}
@Override
public String getStateName() {
return "已取消";
}
}
// 退款处理中状态
class RefundProcessingState implements OrderState {
@Override
public void process(OrderContext context) {
System.out.println("退款处理中的订单不能处理");
}
@Override
public void cancel(OrderContext context) {
System.out.println("退款处理中,不能取消");
}
@Override
public void pay(OrderContext context) {
System.out.println("退款处理中,不能支付");
}
@Override
public String getStateName() {
return "退款处理中";
}
}
// 测试类
public class StatePatternDemo {
public static void main(String[] args) {
OrderContext order = new OrderContext("2024001");
// 测试状态流转
order.process(); // 新建 -> 处理中
order.pay(); // 处理中 -> 已支付
order.cancel(); // 已支付 -> 退款处理中
// 测试无效操作
order.process(); // 退款处理中,不能处理
}
}
实际案例:电梯控制系统
// 电梯状态接口
interface ElevatorState {
void openDoor(ElevatorContext context);
void closeDoor(ElevatorContext context);
void moveUp(ElevatorContext context);
void moveDown(ElevatorContext context);
void stop(ElevatorContext context);
String getStateName();
}
// 电梯上下文
class ElevatorContext {
private ElevatorState currentState;
private int currentFloor;
public ElevatorContext() {
this.currentState = new IdleState();
this.currentFloor = 1;
}
public void setState(ElevatorState state) {
System.out.println("电梯状态变更: " + currentState.getStateName()
+ " -> " + state.getStateName());
this.currentState = state;
}
public ElevatorState getState() {
return currentState;
}
public int getCurrentFloor() {
return currentFloor;
}
public void setCurrentFloor(int floor) {
this.currentFloor = floor;
}
public void openDoor() { currentState.openDoor(this); }
public void closeDoor() { currentState.closeDoor(this); }
public void moveUp() { currentState.moveUp(this); }
public void moveDown() { currentState.moveDown(this); }
public void stop() { currentState.stop(this); }
}
// 空闲状态
class IdleState implements ElevatorState {
@Override
public void openDoor(ElevatorContext context) {
System.out.println("电梯门打开");
context.setState(new DoorOpenState());
}
@Override
public void closeDoor(ElevatorContext context) {
System.out.println("电梯门已经关闭");
}
@Override
public void moveUp(ElevatorContext context) {
System.out.println("电梯开始上行");
context.setState(new MovingUpState());
}
@Override
public void moveDown(ElevatorContext context) {
System.out.println("电梯开始下行");
context.setState(new MovingDownState());
}
@Override
public void stop(ElevatorContext context) {
System.out.println("电梯已经停止");
}
@Override
public String getStateName() {
return "空闲";
}
}
// 门打开状态
class DoorOpenState implements ElevatorState {
@Override
public void openDoor(ElevatorContext context) {
System.out.println("门已经打开");
}
@Override
public void closeDoor(ElevatorContext context) {
System.out.println("电梯门关闭");
context.setState(new IdleState());
}
@Override
public void moveUp(ElevatorContext context) {
System.out.println("门未关闭,不能移动");
}
@Override
public void moveDown(ElevatorContext context) {
System.out.println("门未关闭,不能移动");
}
@Override
public void stop(ElevatorContext context) {
System.out.println("门已打开,处于停止状态");
}
@Override
public String getStateName() {
return "门打开";
}
}
// 上行状态
class MovingUpState implements ElevatorState {
@Override
public void openDoor(ElevatorContext context) {
System.out.println("运行中不能开门");
}
@Override
public void closeDoor(ElevatorContext context) {
System.out.println("运行中门已关闭");
}
@Override
public void moveUp(ElevatorContext context) {
context.setCurrentFloor(context.getCurrentFloor() + 1);
System.out.println("上行至 " + context.getCurrentFloor() + " 层");
}
@Override
public void moveDown(ElevatorContext context) {
System.out.println("正在上行,不能直接下行");
}
@Override
public void stop(ElevatorContext context) {
System.out.println("电梯停止");
context.setState(new IdleState());
}
@Override
public String getStateName() {
return "上行中";
}
}
// 下行状态
class MovingDownState implements ElevatorState {
@Override
public void openDoor(ElevatorContext context) {
System.out.println("运行中不能开门");
}
@Override
public void closeDoor(ElevatorContext context) {
System.out.println("运行中门已关闭");
}
@Override
public void moveUp(ElevatorContext context) {
System.out.println("正在下行,不能直接上行");
}
@Override
public void moveDown(ElevatorContext context) {
context.setCurrentFloor(context.getCurrentFloor() - 1);
System.out.println("下行至 " + context.getCurrentFloor() + " 层");
}
@Override
public void stop(ElevatorContext context) {
System.out.println("电梯停止");
context.setState(new IdleState());
}
@Override
public String getStateName() {
return "下行中";
}
}
// 测试类
public class ElevatorDemo {
public static void main(String[] args) {
ElevatorContext elevator = new ElevatorContext();
// 测试电梯操作
elevator.openDoor(); // 空闲 -> 门打开
elevator.closeDoor(); // 门打开 -> 空闲
elevator.moveUp(); // 空闲 -> 上行中
elevator.moveUp(); // 继续上行
elevator.stop(); // 上行中 -> 空闲
elevator.openDoor(); // 空闲 -> 门打开
elevator.moveUp(); // 门打开状态,不能移动
elevator.closeDoor(); // 门打开 -> 空闲
}
}
状态模式的优缺点
优点:
- 单一职责原则:将与特定状态相关的代码组织到单独的类中
- 开闭原则:增加新状态容易,无需修改现有状态类
- 消除庞大的条件分支语句
- 状态转换逻辑清晰,集中在状态类中
缺点:
- 类数量增加,管理复杂
- 状态转换逻辑分散在多个状态类中
- 如果状态简单,使用状态模式可能过度设计
实际应用场景
- 订单系统、审批流程
- 游戏角色状态(待机、攻击、防御)
- UI组件状态(可编辑、只读、禁用)
- 网络连接状态
- 音视频播放器状态