状态模式
大约 13 分钟
状态模式
什么是状态模式
状态模式(State Pattern)是一种行为型设计模式,它允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类。状态模式将对象的状态封装成独立的类,并将不同状态的行为分散到这些类中,从而消除庞大的条件分支语句。
状态模式的核心思想是:
- 将对象的状态封装成独立的类
- 每个状态类实现状态相关的操作
- 对象在不同状态下表现出不同的行为
- 状态之间可以相互转换
为什么需要状态模式
在实际开发中,我们经常会遇到一个对象在不同状态下具有不同行为的情况。如果使用大量的条件语句(if-else或switch-case)来处理不同状态下的行为,会导致代码复杂、难以维护和扩展。状态模式通过将每个状态的行为封装到独立的类中,使得状态的增加、修改和删除变得更加容易,同时也提高了代码的可读性和可维护性。
状态模式的结构
状态模式包含以下几个角色:
- 环境类(Context):定义客户感兴趣的接口,维护一个具体状态类的实例
- 抽象状态类(State):定义一个接口以封装与环境类的一个特定状态相关的行为
- 具体状态类(ConcreteState):每一个具体状态类都实现了环境类的一个状态相关的行为
状态模式的实现
基本实现
// 抽象状态类
abstract class State {
public abstract void handle(Context context);
}
// 环境类
class Context {
private State state;
public Context(State state) {
this.state = state;
}
public void setState(State state) {
this.state = state;
}
public State getState() {
return state;
}
public void request() {
state.handle(this);
}
}
// 具体状态A
class ConcreteStateA extends State {
@Override
public void handle(Context context) {
System.out.println("处理状态A的业务逻辑");
// 状态转换到状态B
context.setState(new ConcreteStateB());
}
}
// 具体状态B
class ConcreteStateB extends State {
@Override
public void handle(Context context) {
System.out.println("处理状态B的业务逻辑");
// 状态转换到状态A
context.setState(new ConcreteStateA());
}
}
// 使用示例
public class StateDemo {
public static void main(String[] args) {
// 创建环境对象,初始状态为状态A
Context context = new Context(new ConcreteStateA());
// 多次请求,观察状态变化
System.out.println("=== 状态模式演示 ===");
context.request();
context.request();
context.request();
context.request();
}
}
改进的实现(状态共享)
// 改进的抽象状态类
abstract class ImprovedState {
// 使用静态常量避免重复创建状态对象
public static final ImprovedState STATE_A = new ConcreteImprovedStateA();
public static final ImprovedState STATE_B = new ConcreteImprovedStateB();
public static final ImprovedState STATE_C = new ConcreteImprovedStateC();
public abstract void handle(ImprovedContext context);
}
// 改进的环境类
class ImprovedContext {
private ImprovedState state;
public ImprovedContext(ImprovedState state) {
this.state = state;
}
public void setState(ImprovedState state) {
this.state = state;
}
public ImprovedState getState() {
return state;
}
public void request() {
state.handle(this);
}
}
// 改进的具体状态A
class ConcreteImprovedStateA extends ImprovedState {
@Override
public void handle(ImprovedContext context) {
System.out.println("处理改进状态A的业务逻辑");
// 状态转换到状态B
context.setState(ImprovedState.STATE_B);
}
}
// 改进的具体状态B
class ConcreteImprovedStateB extends ImprovedState {
@Override
public void handle(ImprovedContext context) {
System.out.println("处理改进状态B的业务逻辑");
// 状态转换到状态C
context.setState(ImprovedState.STATE_C);
}
}
// 改进的具体状态C
class ConcreteImprovedStateC extends ImprovedState {
@Override
public void handle(ImprovedContext context) {
System.out.println("处理改进状态C的业务逻辑");
// 状态转换到状态A
context.setState(ImprovedState.STATE_A);
}
}
// 使用示例
public class ImprovedStateDemo {
public static void main(String[] args) {
// 创建环境对象,初始状态为状态A
ImprovedContext context = new ImprovedContext(ImprovedState.STATE_A);
// 多次请求,观察状态变化
System.out.println("=== 改进的状态模式演示 ===");
context.request();
context.request();
context.request();
context.request();
context.request();
}
}
状态模式的应用场景
- 工作流系统:订单状态、审批流程等
- 游戏开发:游戏角色状态、游戏状态等
- 网络连接:TCP连接状态管理
- 电梯控制系统:电梯运行状态管理
- 播放器控制:播放、暂停、停止等状态
- 线程状态管理:Java线程状态转换
状态模式的优缺点
优点
- 消除复杂的条件分支语句:将每个状态的行为封装到独立的类中
- 提高代码的可维护性:状态的增加、修改和删除更加容易
- 符合开闭原则:增加新的状态无须修改原有代码
- 使状态转换更加明确:状态之间的转换变得更加清晰
缺点
- 增加类的数量:每个状态都需要一个类,可能会增加系统中类的数量
- 状态逻辑分散:状态相关的代码分散在多个类中,可能增加理解难度
- 状态转换复杂:如果状态转换逻辑复杂,可能会增加设计难度
状态模式与其他模式的比较
与策略模式的区别
- 状态模式:状态之间可以相互转换,对象的行为随着状态的改变而改变
- 策略模式:算法之间不能相互转换,客户端主动选择算法
与有限状态机的区别
- 状态模式:面向对象的实现方式,将状态封装成对象
- 有限状态机:数学模型,使用状态表或状态图来描述状态转换
与命令模式的区别
- 状态模式:关注对象状态的改变对行为的影响
- 命令模式:关注将请求封装成对象
实际项目中的应用
// 电梯控制系统示例
// 电梯状态抽象类
abstract class ElevatorState {
// 电梯状态常量
public static final ElevatorState IDLE = new IdleState();
public static final ElevatorState MOVING_UP = new MovingUpState();
public static final ElevatorState MOVING_DOWN = new MovingDownState();
public static final ElevatorState STOPPED = new StoppedState();
public static final ElevatorState DOOR_OPEN = new DoorOpenState();
public static final ElevatorState DOOR_CLOSED = new DoorClosedState();
// 状态相关操作
public abstract void openDoor(Elevator elevator);
public abstract void closeDoor(Elevator elevator);
public abstract void moveUp(Elevator elevator);
public abstract void moveDown(Elevator elevator);
public abstract void stop(Elevator elevator);
public abstract void idle(Elevator elevator);
}
// 电梯类
class Elevator {
private ElevatorState state;
private int currentFloor;
private int targetFloor;
public Elevator() {
this.state = ElevatorState.IDLE;
this.currentFloor = 1;
this.targetFloor = 1;
}
public void setState(ElevatorState state) {
this.state = state;
}
public ElevatorState getState() {
return state;
}
public int getCurrentFloor() {
return currentFloor;
}
public void setCurrentFloor(int currentFloor) {
this.currentFloor = currentFloor;
}
public int getTargetFloor() {
return targetFloor;
}
public void setTargetFloor(int targetFloor) {
this.targetFloor = targetFloor;
}
// 电梯操作
public void openDoor() {
state.openDoor(this);
}
public void closeDoor() {
state.closeDoor(this);
}
public void moveUp() {
state.moveUp(this);
}
public void moveDown() {
state.moveDown(this);
}
public void stop() {
state.stop(this);
}
public void idle() {
state.idle(this);
}
@Override
public String toString() {
return "电梯在 " + currentFloor + " 楼,目标楼层 " + targetFloor + ",状态: " + state.getClass().getSimpleName();
}
}
// 空闲状态
class IdleState extends ElevatorState {
@Override
public void openDoor(Elevator elevator) {
System.out.println("电梯开门");
elevator.setState(ElevatorState.DOOR_OPEN);
}
@Override
public void closeDoor(Elevator elevator) {
System.out.println("电梯门已关闭");
elevator.setState(ElevatorState.DOOR_CLOSED);
}
@Override
public void moveUp(Elevator elevator) {
System.out.println("电梯开始上行");
elevator.setState(ElevatorState.MOVING_UP);
}
@Override
public void moveDown(Elevator elevator) {
System.out.println("电梯开始下行");
elevator.setState(ElevatorState.MOVING_DOWN);
}
@Override
public void stop(Elevator elevator) {
System.out.println("电梯已停止");
elevator.setState(ElevatorState.STOPPED);
}
@Override
public void idle(Elevator elevator) {
System.out.println("电梯空闲");
}
}
// 上行状态
class MovingUpState extends ElevatorState {
@Override
public void openDoor(Elevator elevator) {
System.out.println("电梯正在上行,无法开门");
}
@Override
public void closeDoor(Elevator elevator) {
System.out.println("电梯正在上行");
}
@Override
public void moveUp(Elevator elevator) {
int currentFloor = elevator.getCurrentFloor();
int targetFloor = elevator.getTargetFloor();
if (currentFloor < targetFloor) {
elevator.setCurrentFloor(currentFloor + 1);
System.out.println("电梯上行到 " + elevator.getCurrentFloor() + " 楼");
} else {
System.out.println("已到达目标楼层 " + targetFloor);
elevator.setState(ElevatorState.STOPPED);
}
}
@Override
public void moveDown(Elevator elevator) {
System.out.println("电梯正在上行,无法下行");
}
@Override
public void stop(Elevator elevator) {
System.out.println("电梯紧急停止");
elevator.setState(ElevatorState.STOPPED);
}
@Override
public void idle(Elevator elevator) {
System.out.println("电梯正在运行");
}
}
// 下行状态
class MovingDownState extends ElevatorState {
@Override
public void openDoor(Elevator elevator) {
System.out.println("电梯正在下行,无法开门");
}
@Override
public void closeDoor(Elevator elevator) {
System.out.println("电梯正在下行");
}
@Override
public void moveUp(Elevator elevator) {
System.out.println("电梯正在下行,无法上行");
}
@Override
public void moveDown(Elevator elevator) {
int currentFloor = elevator.getCurrentFloor();
int targetFloor = elevator.getTargetFloor();
if (currentFloor > targetFloor) {
elevator.setCurrentFloor(currentFloor - 1);
System.out.println("电梯下行到 " + elevator.getCurrentFloor() + " 楼");
} else {
System.out.println("已到达目标楼层 " + targetFloor);
elevator.setState(ElevatorState.STOPPED);
}
}
@Override
public void stop(Elevator elevator) {
System.out.println("电梯紧急停止");
elevator.setState(ElevatorState.STOPPED);
}
@Override
public void idle(Elevator elevator) {
System.out.println("电梯正在运行");
}
}
// 停止状态
class StoppedState extends ElevatorState {
@Override
public void openDoor(Elevator elevator) {
System.out.println("电梯开门");
elevator.setState(ElevatorState.DOOR_OPEN);
}
@Override
public void closeDoor(Elevator elevator) {
System.out.println("电梯门已关闭");
elevator.setState(ElevatorState.DOOR_CLOSED);
}
@Override
public void moveUp(Elevator elevator) {
System.out.println("电梯准备上行");
elevator.setState(ElevatorState.MOVING_UP);
}
@Override
public void moveDown(Elevator elevator) {
System.out.println("电梯准备下行");
elevator.setState(ElevatorState.MOVING_DOWN);
}
@Override
public void stop(Elevator elevator) {
System.out.println("电梯已停止");
}
@Override
public void idle(Elevator elevator) {
System.out.println("电梯进入空闲状态");
elevator.setState(ElevatorState.IDLE);
}
}
// 开门状态
class DoorOpenState extends ElevatorState {
@Override
public void openDoor(Elevator elevator) {
System.out.println("电梯门已开启");
}
@Override
public void closeDoor(Elevator elevator) {
System.out.println("电梯关门");
elevator.setState(ElevatorState.DOOR_CLOSED);
}
@Override
public void moveUp(Elevator elevator) {
System.out.println("电梯门开启时无法运行");
}
@Override
public void moveDown(Elevator elevator) {
System.out.println("电梯门开启时无法运行");
}
@Override
public void stop(Elevator elevator) {
System.out.println("电梯门开启");
}
@Override
public void idle(Elevator elevator) {
System.out.println("电梯门开启");
}
}
// 关门状态
class DoorClosedState extends ElevatorState {
@Override
public void openDoor(Elevator elevator) {
System.out.println("电梯开门");
elevator.setState(ElevatorState.DOOR_OPEN);
}
@Override
public void closeDoor(Elevator elevator) {
System.out.println("电梯门已关闭");
}
@Override
public void moveUp(Elevator elevator) {
System.out.println("电梯准备上行");
elevator.setState(ElevatorState.MOVING_UP);
}
@Override
public void moveDown(Elevator elevator) {
System.out.println("电梯准备下行");
elevator.setState(ElevatorState.MOVING_DOWN);
}
@Override
public void stop(Elevator elevator) {
System.out.println("电梯已停止");
elevator.setState(ElevatorState.STOPPED);
}
@Override
public void idle(Elevator elevator) {
System.out.println("电梯进入空闲状态");
elevator.setState(ElevatorState.IDLE);
}
}
// 电梯控制系统
public class ElevatorControlSystem {
public static void main(String[] args) throws InterruptedException {
// 创建电梯
Elevator elevator = new Elevator();
// 模拟电梯运行
System.out.println("=== 电梯控制系统演示 ===");
System.out.println("初始状态: " + elevator);
// 设置目标楼层
elevator.setTargetFloor(5);
System.out.println("\n1. 设置目标楼层为 5 楼");
// 电梯上行
System.out.println("\n2. 电梯开始上行:");
while (elevator.getState() != ElevatorState.STOPPED) {
elevator.moveUp();
Thread.sleep(1000); // 模拟时间延迟
}
// 开门
System.out.println("\n3. 到达目标楼层,开门:");
elevator.openDoor();
// 关门
System.out.println("\n4. 关门:");
elevator.closeDoor();
// 设置新目标楼层
elevator.setTargetFloor(2);
System.out.println("\n5. 设置目标楼层为 2 楼");
// 电梯下行
System.out.println("\n6. 电梯开始下行:");
while (elevator.getState() != ElevatorState.STOPPED) {
elevator.moveDown();
Thread.sleep(1000); // 模拟时间延迟
}
// 开门
System.out.println("\n7. 到达目标楼层,开门:");
elevator.openDoor();
// 进入空闲状态
System.out.println("\n8. 关门并进入空闲状态:");
elevator.closeDoor();
elevator.idle();
System.out.println("最终状态: " + elevator);
}
}
// 工作流系统示例
// 订单状态抽象类
abstract class OrderState {
// 订单状态常量
public static final OrderState PENDING = new PendingState();
public static final OrderState CONFIRMED = new ConfirmedState();
public static final OrderState PAID = new PaidState();
public static final OrderState SHIPPED = new ShippedState();
public static final OrderState DELIVERED = new DeliveredState();
public static final OrderState CANCELLED = new CancelledState();
// 状态相关操作
public abstract void confirm(Order order);
public abstract void pay(Order order);
public abstract void ship(Order order);
public abstract void deliver(Order order);
public abstract void cancel(Order order);
// 获取状态名称
public abstract String getStateName();
}
// 订单类
class Order {
private OrderState state;
private String orderId;
private double amount;
public Order(String orderId, double amount) {
this.orderId = orderId;
this.amount = amount;
this.state = OrderState.PENDING;
}
public void setState(OrderState state) {
this.state = state;
}
public OrderState getState() {
return state;
}
public String getOrderId() {
return orderId;
}
public double getAmount() {
return amount;
}
// 订单操作
public void confirm() {
System.out.println("确认订单 " + orderId);
state.confirm(this);
}
public void pay() {
System.out.println("支付订单 " + orderId + ",金额: $" + amount);
state.pay(this);
}
public void ship() {
System.out.println("发货订单 " + orderId);
state.ship(this);
}
public void deliver() {
System.out.println("交付订单 " + orderId);
state.deliver(this);
}
public void cancel() {
System.out.println("取消订单 " + orderId);
state.cancel(this);
}
@Override
public String toString() {
return "订单 " + orderId + ",金额: $" + amount + ",状态: " + state.getStateName();
}
}
// 待确认状态
class PendingState extends OrderState {
@Override
public void confirm(Order order) {
System.out.println("订单 " + order.getOrderId() + " 已确认");
order.setState(OrderState.CONFIRMED);
}
@Override
public void pay(Order order) {
System.out.println("订单未确认,无法支付");
}
@Override
public void ship(Order order) {
System.out.println("订单未确认,无法发货");
}
@Override
public void deliver(Order order) {
System.out.println("订单未确认,无法交付");
}
@Override
public void cancel(Order order) {
System.out.println("订单 " + order.getOrderId() + " 已取消");
order.setState(OrderState.CANCELLED);
}
@Override
public String getStateName() {
return "待确认";
}
}
// 已确认状态
class ConfirmedState extends OrderState {
@Override
public void confirm(Order order) {
System.out.println("订单已确认");
}
@Override
public void pay(Order order) {
System.out.println("订单 " + order.getOrderId() + " 已支付");
order.setState(OrderState.PAID);
}
@Override
public void ship(Order order) {
System.out.println("订单未支付,无法发货");
}
@Override
public void deliver(Order order) {
System.out.println("订单未支付,无法交付");
}
@Override
public void cancel(Order order) {
System.out.println("订单 " + order.getOrderId() + " 已取消");
order.setState(OrderState.CANCELLED);
}
@Override
public String getStateName() {
return "已确认";
}
}
// 已支付状态
class PaidState extends OrderState {
@Override
public void confirm(Order order) {
System.out.println("订单已支付,无需再次确认");
}
@Override
public void pay(Order order) {
System.out.println("订单已支付");
}
@Override
public void ship(Order order) {
System.out.println("订单 " + order.getOrderId() + " 已发货");
order.setState(OrderState.SHIPPED);
}
@Override
public void deliver(Order order) {
System.out.println("订单未发货,无法交付");
}
@Override
public void cancel(Order order) {
System.out.println("订单已支付,无法取消");
}
@Override
public String getStateName() {
return "已支付";
}
}
// 已发货状态
class ShippedState extends OrderState {
@Override
public void confirm(Order order) {
System.out.println("订单已发货");
}
@Override
public void pay(Order order) {
System.out.println("订单已发货");
}
@Override
public void ship(Order order) {
System.out.println("订单已发货");
}
@Override
public void deliver(Order order) {
System.out.println("订单 " + order.getOrderId() + " 已交付");
order.setState(OrderState.DELIVERED);
}
@Override
public void cancel(Order order) {
System.out.println("订单已发货,无法取消");
}
@Override
public String getStateName() {
return "已发货";
}
}
// 已交付状态
class DeliveredState extends OrderState {
@Override
public void confirm(Order order) {
System.out.println("订单已完成");
}
@Override
public void pay(Order order) {
System.out.println("订单已完成");
}
@Override
public void ship(Order order) {
System.out.println("订单已完成");
}
@Override
public void deliver(Order order) {
System.out.println("订单已完成");
}
@Override
public void cancel(Order order) {
System.out.println("订单已完成,无法取消");
}
@Override
public String getStateName() {
return "已交付";
}
}
// 已取消状态
class CancelledState extends OrderState {
@Override
public void confirm(Order order) {
System.out.println("订单已取消");
}
@Override
public void pay(Order order) {
System.out.println("订单已取消");
}
@Override
public void ship(Order order) {
System.out.println("订单已取消");
}
@Override
public void deliver(Order order) {
System.out.println("订单已取消");
}
@Override
public void cancel(Order order) {
System.out.println("订单已取消");
}
@Override
public String getStateName() {
return "已取消";
}
}
// 订单管理系统
public class OrderManagementSystem {
public static void main(String[] args) {
// 创建订单
Order order = new Order("ORD001", 99.99);
// 模拟订单流程
System.out.println("=== 订单管理系统演示 ===");
System.out.println("1. 创建订单: " + order);
// 确认订单
System.out.println("\n2. 确认订单:");
order.confirm();
System.out.println("当前状态: " + order);
// 支付订单
System.out.println("\n3. 支付订单:");
order.pay();
System.out.println("当前状态: " + order);
// 发货订单
System.out.println("\n4. 发货订单:");
order.ship();
System.out.println("当前状态: " + order);
// 交付订单
System.out.println("\n5. 交付订单:");
order.deliver();
System.out.println("当前状态: " + order);
// 尝试取消已完成的订单
System.out.println("\n6. 尝试取消已完成的订单:");
order.cancel();
System.out.println("最终状态: " + order);
// 创建新订单并取消
System.out.println("\n=== 取消订单演示 ===");
Order order2 = new Order("ORD002", 199.99);
System.out.println("1. 创建订单: " + order2);
System.out.println("\n2. 取消订单:");
order2.cancel();
System.out.println("最终状态: " + order2);
}
}
Java中的状态模式应用
// 线程状态示例
// 模拟Java线程状态的简化版本
enum ThreadState {
NEW, RUNNABLE, BLOCKED, WAITING, TIMED_WAITING, TERMINATED
}
class SimpleThread {
private ThreadState state;
private String name;
public SimpleThread(String name) {
this.name = name;
this.state = ThreadState.NEW;
System.out.println("创建线程 " + name + ",状态: " + state);
}
public void start() {
if (state == ThreadState.NEW) {
state = ThreadState.RUNNABLE;
System.out.println("启动线程 " + name + ",状态: " + state);
} else {
System.out.println("线程 " + name + " 无法启动,当前状态: " + state);
}
}
public void sleep(long millis) {
if (state == ThreadState.RUNNABLE) {
state = ThreadState.TIMED_WAITING;
System.out.println("线程 " + name + " 睡眠 " + millis + " 毫秒,状态: " + state);
// 模拟睡眠
try {
Thread.sleep(millis);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
state = ThreadState.RUNNABLE;
System.out.println("线程 " + name + " 醒来,状态: " + state);
} else {
System.out.println("线程 " + name + " 无法睡眠,当前状态: " + state);
}
}
public void block() {
if (state == ThreadState.RUNNABLE) {
state = ThreadState.BLOCKED;
System.out.println("线程 " + name + " 被阻塞,状态: " + state);
} else {
System.out.println("线程 " + name + " 无法阻塞,当前状态: " + state);
}
}
public void unblock() {
if (state == ThreadState.BLOCKED) {
state = ThreadState.RUNNABLE;
System.out.println("线程 " + name + " 解除阻塞,状态: " + state);
} else {
System.out.println("线程 " + name + " 无需解除阻塞,当前状态: " + state);
}
}
public void terminate() {
if (state != ThreadState.TERMINATED) {
state = ThreadState.TERMINATED;
System.out.println("线程 " + name + " 终止,状态: " + state);
} else {
System.out.println("线程 " + name + " 已终止");
}
}
public ThreadState getState() {
return state;
}
public String getName() {
return name;
}
}
// 使用示例
public class ThreadStateDemo {
public static void main(String[] args) throws InterruptedException {
// 创建线程
SimpleThread thread = new SimpleThread("WorkerThread");
// 启动线程
thread.start();
// 线程睡眠
thread.sleep(1000);
// 阻塞线程
thread.block();
// 解除阻塞
thread.unblock();
// 终止线程
thread.terminate();
// 尝试对已终止的线程进行操作
thread.start();
thread.terminate();
}
}
总结
状态模式是一种非常实用的行为型设计模式,它允许对象在内部状态改变时改变它的行为,使得对象看起来好像修改了它的类。状态模式通过将每个状态的行为封装到独立的类中,消除了复杂的条件分支语句,提高了代码的可维护性和可扩展性。
使用状态模式的关键点:
- 识别对象的不同状态和状态相关的行为
- 定义抽象状态类和具体状态类
- 在环境类中维护当前状态并委托状态类处理行为
- 实现状态之间的转换逻辑
状态模式的优点是能够消除复杂的条件分支语句,提高代码的可维护性,符合开闭原则。但需要注意的是,会增加系统中类的数量,状态逻辑分散在多个类中。在现代Java开发中,状态模式广泛应用于工作流系统、游戏开发、网络连接管理、播放器控制等需要状态管理的场景。