状态模式(State Pattern) 是一种行为设计模式,将状态封装为独立的类,并将动作委托给代表当前状态的对象。允许对象在其内部状态改变时改变其行为。
特点
1、将状态相关的行为封装在不同的状态类中;2、上下文对象(Context)的行为会随着其状态的改变而改变;2、消除了复杂的条件判断语句,使代码更易于维护和扩展
结构
状态模式结构包括三个部分:
-
Context(上下文):
-
维护一个ConcreteState子类的实例,定义当前状态
-
提供客户端调用的接口,将请求委托给当前状态对象处理
-
-
State(状态接口):
-
定义状态行为的接口
-
封装与Context特定状态相关的行为
-
-
ConcreteState(具体状态):
-
实现State接口
-
实现与Context某个状态相关的行为
-
UML对象图如下:
代码示例
java
// 1. 状态接口
interface OrderState {
// 订单处理
void process(OrderContext order);
// 订单取消
void cancel(OrderContext order);
// 订单发货
void ship(OrderContext order);
// 订单送达
void deliver(OrderContext order);
String getStateName();
}
// 2. 抽象状态类(提供默认实现)
abstract class AbstractOrderState implements OrderState {
@Override
public void process(OrderContext order) {
throw new UnsupportedOperationException("当前状态不支持此操作");
}
@Override
public void cancel(OrderContext order) {
throw new UnsupportedOperationException("当前状态不支持此操作");
}
@Override
public void ship(OrderContext order) {
throw new UnsupportedOperationException("当前状态不支持此操作");
}
@Override
public void deliver(OrderContext order) {
throw new UnsupportedOperationException("当前状态不支持此操作");
}
}
// 3. 具体状态类
class NewOrderState extends AbstractOrderState {
@Override
public void process(OrderContext order) {
System.out.println("处理新订单...");
order.setState(new ProcessingOrderState());
}
@Override
public void cancel(OrderContext order) {
System.out.println("取消新订单");
order.setState(new CancelledOrderState());
}
@Override
public String getStateName() {
return "新订单";
}
}
class ProcessingOrderState extends AbstractOrderState {
@Override
public void ship(OrderContext order) {
System.out.println("订单已发货");
order.setState(new ShippedOrderState());
}
@Override
public void cancel(OrderContext order) {
System.out.println("取消处理中的订单");
order.setState(new CancelledOrderState());
}
@Override
public String getStateName() {
return "处理中";
}
}
class ShippedOrderState extends AbstractOrderState {
@Override
public void deliver(OrderContext order) {
System.out.println("订单已送达");
order.setState(new DeliveredOrderState());
}
@Override
public String getStateName() {
return "已发货";
}
}
class DeliveredOrderState extends AbstractOrderState {
@Override
public String getStateName() {
return "已送达";
}
}
class CancelledOrderState extends AbstractOrderState {
@Override
public String getStateName() {
return "已取消";
}
}
// 4. 上下文类
class OrderContext {
private OrderState currentState;
private String orderId;
public OrderContext(String orderId) {
this.orderId = orderId;
this.currentState = new NewOrderState();
}
public void setState(OrderState state) {
this.currentState = state;
System.out.println("订单 [" + orderId + "] 状态变更为: " + state.getStateName());
}
public void process() {
currentState.process(this);
}
public void cancel() {
currentState.cancel(this);
}
public void ship() {
currentState.ship(this);
}
public void deliver() {
currentState.deliver(this);
}
public String getCurrentState() {
return currentState.getStateName();
}
}
// 5. 客户端代码
public class OrderStateDemo {
public static void main(String[] args) {
OrderContext order = new OrderContext("ORD001");
System.out.println("初始状态: " + order.getCurrentState());
try {
order.process(); // 新订单 -> 处理中
order.ship(); // 处理中 -> 已发货
order.deliver(); // 已发货 -> 已送达
// 尝试非法操作
System.out.println("\n尝试取消已送达的订单:");
order.cancel(); // 应该抛出异常
} catch (Exception e) {
System.out.println("操作失败: " + e.getMessage());
}
System.out.println("\n=== 另一个订单 ===");
OrderContext order2 = new OrderContext("ORD002");
order2.cancel(); // 新订单 -> 已取消
}
}
适合场景
-
对象行为依赖于状态 :一个对象的行为取决于它的状态,在运行时根据状态改变行为
-
大量条件判断:操作中含有庞大的多分支条件语句,且这些分支依赖于对象的状态
-
状态转换复杂:状态转换逻辑复杂或状态数量较多
-
需要维护状态历史:需要跟踪状态变化历史
应用案例
-
工作流引擎:文档审批流程、订单处理流程
-
游戏开发:角色状态(站立、行走、奔跑、跳跃、攻击)
-
网络连接:连接状态(建立连接、已连接、断开连接、重新连接)
-
UI组件:按钮状态(正常、悬停、按下、禁用)
-
电梯控制:电梯运行状态(停止、上行、下行、故障)
-
自动售货机:商品选择、付款、出货等状态
-
线程状态管理:新建、就绪、运行、阻塞、终止
优缺点
优点:
1、单一职责原则 :将与特定状态相关的代码组织到独立的类中;2、开闭原则 :增加新状态时无需修改现有状态类或上下文;3、消除条件语句 :减少上下文中复杂的条件判断;4、状态转换显式化 :使状态转换更加明确;5、提高可维护性:状态逻辑局部化,易于理解和维护
缺点:
1、类数量增加 :每个状态都需要一个对应的类,可能导致类数量膨胀;2、过度设计 :如果状态数量很少或状态转换简单,使用状态模式可能增加复杂性;3、状态共享:不同上下文之间共享状态对象时需要确保线程安全
