设计模式详解-状态模式
设计模式详解:状态模式
一、模式概述
状态模式(State Pattern)是行为型设计模式中最具动态行为组织价值的模式,其核心意图在于允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类。状态模式将状态相关的行为局部化到各自的状态类中,消除庞大的条件分支语句,使状态转换显式化、可追踪、可扩展。
状态模式的命名直接揭示了其功能——"状态"即对象在生命周期中某一时刻的条件或情形。在电梯系统中,电梯可能处于停止、运行、开门、关门等状态,每种状态下对同一请求(如按楼层按钮)的响应截然不同;在电商订单中,订单从创建到完结经历待支付、已支付、已发货、已签收、已完成等状态,每个状态决定了可执行的操作和允许的状态迁移;在游戏开发中,角色可能处于站立、行走、奔跑、跳跃、受击等状态,每种状态对应不同的动画和物理行为。这些现实隐喻均指向同一核心特征:将状态作为一等公民,封装状态特有的行为与迁移规则。
状态模式的深层价值在于将"状态-行为-迁移"三元组从隐式的条件判断提升为显式的对象结构。传统方式使用枚举或常量配合switch/if-else判断状态,导致代码中散落着状态相关的条件分支,新增状态需修改多处代码;状态模式将每个状态封装为独立类,状态转换由状态对象自身管理,新增状态只需新增类,符合开闭原则。在工作流引擎、游戏AI、网络协议、设备控制等场景中,状态模式是管理复杂生命周期的不二选择。
二、模式结构
状态模式包含三个核心角色,形成清晰的状态-行为-上下文架构:
上下文(Context):定义客户端感兴趣的接口,维护一个具体状态子类的实例,这个实例定义当前状态。上下文将状态相关的请求委托给当前状态对象处理。
抽象状态(State):定义一个封装与上下文特定状态相关行为的接口,声明状态可执行的操作和允许的状态迁移。
具体状态(Concrete State):实现抽象状态接口,每个子类实现与上下文某个状态相关的行为。具体状态负责处理来自上下文的请求,并决定状态迁移。
状态模式的关键特征在于状态对象拥有行为和数据,且能控制状态迁移。与传统状态机不同,状态模式中的状态不是简单的标记值,而是具有完整行为能力的对象,状态转换逻辑内聚在状态类内部,而非散落在上下文的方法中。
三、深度案例:电商订单生命周期引擎
以下展示一个真实场景下的状态模式应用——电商平台的订单状态机引擎,处理订单从创建到完结的完整生命周期,支持状态校验、行为控制、迁移审计和扩展定制。
3.1 问题域分析:条件分支的泥潭
java
// 反模式:状态与行为耦合在单体类中
@Service
public class NaiveOrderService {
@Autowired private OrderRepository repository;
@Autowired private PaymentService payment;
@Autowired private LogisticsService logistics;
public void pay(String orderId) {
Order order = repository.findById(orderId);
// 状态判断散落在每个方法中
if (order.getStatus() == OrderStatus.CREATED) {
// 可以支付
payment.process(order);
order.setStatus(OrderStatus.PAID);
order.setPayTime(LocalDateTime.now());
repository.save(order);
} else if (order.getStatus() == OrderStatus.PAID) {
throw new IllegalStateException("订单已支付");
} else if (order.getStatus() == OrderStatus.SHIPPED) {
throw new IllegalStateException("订单已发货,无法支付");
} else if (order.getStatus() == OrderStatus.COMPLETED) {
throw new IllegalStateException("订单已完成");
} else if (order.getStatus() == OrderStatus.CANCELLED) {
throw new IllegalStateException("订单已取消");
}
// 新增状态需修改所有方法
}
public void ship(String orderId) {
Order order = repository.findById(orderId);
if (order.getStatus() == OrderStatus.PAID) {
logistics.createShipment(order);
order.setStatus(OrderStatus.SHIPPED);
order.setShipTime(LocalDateTime.now());
repository.save(order);
} else if (order.getStatus() == OrderStatus.CREATED) {
throw new IllegalStateException("订单未支付");
}
// 重复的状态判断...
}
public void cancel(String orderId) {
Order order = repository.findById(orderId);
// 取消规则复杂:未支付可直接取消,已支付需退款,已发货需拦截
if (order.getStatus() == OrderStatus.CREATED) {
order.setStatus(OrderStatus.CANCELLED);
} else if (order.getStatus() == OrderStatus.PAID) {
payment.refund(order);
order.setStatus(OrderStatus.CANCELLED);
} else if (order.getStatus() == OrderStatus.SHIPPED) {
logistics.intercept(order);
payment.refund(order);
order.setStatus(OrderStatus.CANCELLED);
} else {
throw new IllegalStateException("当前状态不可取消");
}
repository.save(order);
}
// 每个操作方法都包含重复的状态判断和异常处理
// 状态与行为严重耦合,新增状态需修改所有方法
}
上述代码中,状态判断散落在每个业务方法中,形成"箭头型"代码结构,新增状态需修改所有方法,状态迁移规则隐式且易错。状态模式将状态相关行为封装到状态类中,上下文只负责委托请求。
3.2 抽象层:状态接口与上下文
java
/**
* 抽象状态:定义订单各状态可执行的操作
*/
public interface OrderState {
/**
* 状态标识
*/
OrderStatus getStatus();
/**
* 支付操作
* @param context 订单上下文
* @param paymentParam 支付参数
* @return 支付结果
*/
PayResult pay(OrderContext context, PaymentParam paymentParam);
/**
* 发货操作
* @param context 订单上下文
* @param shipmentParam 发货参数
* @return 发货结果
*/
ShipResult ship(OrderContext context, ShipmentParam shipmentParam);
/**
* 确认收货
* @param context 订单上下文
* @return 确认结果
*/
ReceiveResult confirmReceive(OrderContext context);
/**
* 取消订单
* @param context 订单上下文
* @param reason 取消原因
* @return 取消结果
*/
CancelResult cancel(OrderContext context, String reason);
/**
* 申请退款
* @param context 订单上下文
* @param refundParam 退款参数
* @return 退款申请结果
*/
RefundResult applyRefund(OrderContext context, RefundParam refundParam);
/**
* 自动超时处理
* @param context 订单上下文
* @return 超时处理结果
*/
TimeoutResult handleTimeout(OrderContext context);
/**
* 获取当前状态允许的操作列表(用于前端展示)
*/
List<OrderAction> getAvailableActions();
/**
* 状态进入时的钩子
*/
void onEnter(OrderContext context, OrderState previousState);
/**
* 状态离开时的钩子
*/
void onExit(OrderContext context, OrderState nextState);
}
/**
* 订单上下文:状态模式的核心载体
*/
@Component
public class OrderContext {
private final String orderId;
private OrderState currentState;
private final OrderRepository repository;
private final StateTransitionLogRepository logRepository;
private final ApplicationEventPublisher eventPublisher;
private final MeterRegistry metrics;
// 订单数据
private OrderData data;
public OrderContext(String orderId, OrderRepository repository,
StateTransitionLogRepository logRepository,
ApplicationEventPublisher eventPublisher,
MeterRegistry metrics) {
this.orderId = orderId;
this.repository = repository;
this.logRepository = logRepository;
this.eventPublisher = eventPublisher;
this.metrics = metrics;
loadState();
}
/**
* 从持久化加载当前状态
*/
private void loadState() {
OrderEntity entity = repository.findById(orderId)
.orElseThrow(() -> new OrderNotFoundException(orderId));
this.data = OrderData.from(entity);
this.currentState = StateFactory.create(data.getStatus());
}
/**
* 状态委托:所有操作委托给当前状态对象
*/
public PayResult pay(PaymentParam param) {
return currentState.pay(this, param);
}
public ShipResult ship(ShipmentParam param) {
return currentState.ship(this, param);
}
public ReceiveResult confirmReceive() {
return currentState.confirmReceive(this);
}
public CancelResult cancel(String reason) {
return currentState.cancel(this, reason);
}
public RefundResult applyRefund(RefundParam param) {
return currentState.applyRefund(this, param);
}
public TimeoutResult handleTimeout() {
return currentState.handleTimeout(this);
}
/**
* 状态迁移:由具体状态调用
*/
public void transitionTo(OrderState newState, String trigger, Object detail) {
OrderState oldState = this.currentState;
// 执行离开钩子
oldState.onExit(this, newState);
// 记录迁移日志
StateTransitionLog log = StateTransitionLog.builder()
.orderId(orderId)
.fromStatus(oldState.getStatus())
.toStatus(newState.getStatus())
.trigger(trigger)
.detail(JsonUtils.toJson(detail))
.operator(getCurrentOperator())
.transitionTime(LocalDateTime.now())
.build();
logRepository.save(log);
// 更新持久化状态
data.setStatus(newState.getStatus());
repository.updateStatus(orderId, newState.getStatus());
// 切换状态对象
this.currentState = newState;
// 执行进入钩子
newState.onEnter(this, oldState);
// 发布领域事件
eventPublisher.publishEvent(new OrderStateChangedEvent(this, oldState, newState));
// 监控
metrics.counter("order.state.transition",
"from", oldState.getStatus().name(),
"to", newState.getStatus().name()).increment();
}
// 数据访问方法
public OrderData getData() { return data; }
public String getOrderId() { return orderId; }
public OrderStatus getCurrentStatus() { return currentState.getStatus(); }
public List<OrderAction> getAvailableActions() { return currentState.getAvailableActions(); }
private String getCurrentOperator() {
return SecurityContextHolder.getContext().getAuthentication().getName();
}
}
/**
* 状态工厂:根据状态标识创建状态对象
*/
@Component
public class StateFactory {
private static final Map<OrderStatus, Supplier<OrderState>> STATE_MAP = new HashMap<>();
@Autowired
public StateFactory(List<OrderState> states) {
for (OrderState state : states) {
STATE_MAP.put(state.getStatus(), () -> state);
}
}
public static OrderState create(OrderStatus status) {
Supplier<OrderState> supplier = STATE_MAP.get(status);
if (supplier == null) throw new IllegalStateException("Unknown state: " + status);
return supplier.get();
}
}
3.3 具体状态:各状态的行为实现
java
/**
* 已创建状态:等待支付
*/
@Component
public class CreatedState implements OrderState {
@Autowired private PaymentService paymentService;
@Autowired private TimeoutConfiguration timeoutConfig;
@Override
public OrderStatus getStatus() { return OrderStatus.CREATED; }
@Override
public PayResult pay(OrderContext context, PaymentParam param) {
// 执行支付
PaymentResult result = paymentService.charge(PaymentRequest.builder()
.orderId(context.getOrderId())
.amount(context.getData().getTotalAmount())
.channel(param.getChannel())
.build());
if (result.isSuccess()) {
// 更新支付信息
context.getData().setPaymentId(result.getTransactionId());
context.getData().setPayTime(LocalDateTime.now());
// 迁移到已支付状态
context.transitionTo(new PaidState(), "PAY", result);
return PayResult.success(result.getTransactionId());
}
return PayResult.failure(result.getErrorCode(), result.getErrorMessage());
}
@Override
public ShipResult ship(OrderContext context, ShipmentParam param) {
return ShipResult.failure("ORDER_UNPAID", "订单未支付,无法发货");
}
@Override
public ReceiveResult confirmReceive(OrderContext context) {
return ReceiveResult.failure("ORDER_UNPAID", "订单未支付");
}
@Override
public CancelResult cancel(OrderContext context, String reason) {
// 未支付订单可直接取消
context.getData().setCancelReason(reason);
context.getData().setCancelTime(LocalDateTime.now());
context.transitionTo(new CancelledState(), "CANCEL", Map.of("reason", reason));
return CancelResult.success();
}
@Override
public RefundResult applyRefund(OrderContext context, RefundParam param) {
return RefundResult.failure("ORDER_UNPAID", "未支付订单无需退款");
}
@Override
public TimeoutResult handleTimeout(OrderContext context) {
// 支付超时自动取消
LocalDateTime createTime = context.getData().getCreateTime();
Duration timeout = timeoutConfig.getPayTimeout();
if (LocalDateTime.now().isAfter(createTime.plus(timeout))) {
context.transitionTo(new CancelledState(), "TIMEOUT_PAY",
Map.of("timeoutMinutes", timeout.toMinutes()));
return TimeoutResult.cancelled("支付超时");
}
return TimeoutResult.noAction();
}
@Override
public List<OrderAction> getAvailableActions() {
return List.of(OrderAction.PAY, OrderAction.CANCEL);
}
@Override
public void onEnter(OrderContext context, OrderState previousState) {
// 启动支付超时定时任务
schedulePayTimeout(context.getOrderId());
}
@Override
public void onExit(OrderContext context, OrderState nextState) {
// 取消超时定时任务
cancelPayTimeout(context.getOrderId());
}
private void schedulePayTimeout(String orderId) { /* 定时任务实现 */ }
private void cancelPayTimeout(String orderId) { /* 取消定时任务 */ }
}
/**
* 已支付状态:等待发货
*/
@Component
public class PaidState implements OrderState {
@Autowired private LogisticsService logisticsService;
@Autowired private InventoryService inventoryService;
@Override
public OrderStatus getStatus() { return OrderStatus.PAID; }
@Override
public PayResult pay(OrderContext context, PaymentParam param) {
return PayResult.failure("ORDER_PAID", "订单已支付");
}
@Override
public ShipResult ship(OrderContext context, ShipmentParam param) {
// 库存预占确认
inventoryService.confirmDeduct(context.getOrderId());
// 创建物流单
ShipmentResult result = logisticsService.createShipment(ShipmentRequest.builder()
.orderId(context.getOrderId())
.warehouseId(param.getWarehouseId())
.items(context.getData().getItems())
.receiver(context.getData().getReceiver())
.build());
if (result.isSuccess()) {
context.getData().setShipmentId(result.getShipmentId());
context.getData().setShipTime(LocalDateTime.now());
context.transitionTo(new ShippedState(), "SHIP", result);
return ShipResult.success(result.getShipmentId());
}
// 发货失败,回滚库存
inventoryService.release(context.getOrderId());
return ShipResult.failure(result.getErrorCode(), result.getErrorMessage());
}
@Override
public ReceiveResult confirmReceive(OrderContext context) {
return ReceiveResult.failure("ORDER_UNSHIPPED", "订单未发货");
}
@Override
public CancelResult cancel(OrderContext context, String reason) {
// 已支付需退款
RefundResult refund = paymentService.refund(RefundRequest.builder()
.orderId(context.getOrderId())
.paymentId(context.getData().getPaymentId())
.amount(context.getData().getTotalAmount())
.reason(reason)
.build());
if (!refund.isSuccess()) {
return CancelResult.failure("REFUND_FAILED", "退款失败: " + refund.getError());
}
context.getData().setCancelReason(reason);
context.getData().setRefundId(refund.getRefundId());
context.getData().setCancelTime(LocalDateTime.now());
context.transitionTo(new CancelledState(), "CANCEL_WITH_REFUND", refund);
return CancelResult.success();
}
@Override
public RefundResult applyRefund(OrderContext context, RefundParam param) {
// 未发货支持全额退款
return executeRefund(context, param, RefundType.FULL);
}
@Override
public TimeoutResult handleTimeout(OrderContext context) {
// 已支付状态检查发货超时
LocalDateTime payTime = context.getData().getPayTime();
Duration timeout = timeoutConfig.getShipTimeout();
if (LocalDateTime.now().isAfter(payTime.plus(timeout))) {
// 自动退款并取消
cancel(context, "发货超时自动取消");
return TimeoutResult.cancelled("发货超时");
}
return TimeoutResult.noAction();
}
@Override
public List<OrderAction> getAvailableActions() {
return List.of(OrderAction.SHIP, OrderAction.CANCEL, OrderAction.APPLY_REFUND);
}
@Override
public void onEnter(OrderContext context, OrderState previousState) {
// 触发支付成功通知
notifyPaymentSuccess(context);
// 启动发货超时检查
scheduleShipTimeout(context.getOrderId());
}
@Override
public void onExit(OrderContext context, OrderState nextState) {
cancelShipTimeout(context.getOrderId());
}
private RefundResult executeRefund(OrderContext context, RefundParam param, RefundType type) {
// 退款逻辑...
}
}
/**
* 已发货状态:等待收货
*/
@Component
public class ShippedState implements OrderState {
@Autowired private LogisticsService logisticsService;
@Override
public OrderStatus getStatus() { return OrderStatus.SHIPPED; }
@Override
public PayResult pay(OrderContext context, PaymentParam param) {
return PayResult.failure("ORDER_SHIPPED", "订单已发货");
}
@Override
public ShipResult ship(OrderContext context, ShipmentParam param) {
return ShipResult.failure("ORDER_SHIPPED", "订单已发货");
}
@Override
public ReceiveResult confirmReceive(OrderContext context) {
// 验证物流状态
LogisticsStatus status = logisticsService.queryStatus(context.getData().getShipmentId());
if (status != LogisticsStatus.DELIVERED) {
return ReceiveResult.failure("NOT_DELIVERED", "物流未送达");
}
context.getData().setReceiveTime(LocalDateTime.now());
context.transitionTo(new CompletedState(), "RECEIVE", null);
return ReceiveResult.success();
}
@Override
public CancelResult cancel(OrderContext context, String reason) {
// 已发货需物流拦截
InterceptResult intercept = logisticsService.intercept(context.getData().getShipmentId());
if (!intercept.isSuccess()) {
return CancelResult.failure("INTERCEPT_FAILED", "物流拦截失败");
}
// 退款
RefundResult refund = paymentService.refund(/*...*/);
context.getData().setCancelReason(reason);
context.transitionTo(new CancelledState(), "CANCEL_WITH_INTERCEPT",
Map.of("intercept", intercept, "refund", refund));
return CancelResult.success();
}
@Override
public RefundResult applyRefund(OrderContext context, RefundParam param) {
// 已发货仅支持退货退款
if (!param.isReturnGoods()) {
return RefundResult.failure("REQUIRE_RETURN", "已发货订单需退货");
}
// 创建售后单
return createAfterSale(context, param, AfterSaleType.RETURN_REFUND);
}
@Override
public TimeoutResult handleTimeout(OrderContext context) {
// 自动确认收货超时
LocalDateTime shipTime = context.getData().getShipTime();
Duration autoConfirmDays = timeoutConfig.getAutoConfirmDays();
if (LocalDateTime.now().isAfter(shipTime.plus(autoConfirmDays))) {
confirmReceive(context); // 自动确认
return TimeoutResult.autoConfirmed("自动确认收货");
}
return TimeoutResult.noAction();
}
@Override
public List<OrderAction> getAvailableActions() {
return List.of(OrderAction.CONFIRM_RECEIVE, OrderAction.APPLY_REFUND, OrderAction.CANCEL);
}
@Override
public void onEnter(OrderContext context, OrderState previousState) {
notifyShipped(context);
scheduleAutoConfirm(context.getOrderId());
}
}
/**
* 已完成状态:交易结束
*/
@Component
public class CompletedState implements OrderState {
@Override
public OrderStatus getStatus() { return OrderStatus.COMPLETED; }
@Override
public PayResult pay(OrderContext context, PaymentParam param) {
return PayResult.failure("ORDER_COMPLETED", "订单已完成");
}
@Override
public ShipResult ship(OrderContext context, ShipmentParam param) {
return ShipResult.failure("ORDER_COMPLETED", "订单已完成");
}
@Override
public ReceiveResult confirmReceive(OrderContext context) {
return ReceiveResult.failure("ORDER_COMPLETED", "已确认收货");
}
@Override
public CancelResult cancel(OrderContext context, String reason) {
return CancelResult.failure("ORDER_COMPLETED", "已完成订单不可取消");
}
@Override
public RefundResult applyRefund(OrderContext context, RefundParam param) {
// 完成后仅支持售后
return createAfterSale(context, param, AfterSaleType.AFTER_SALE);
}
@Override
public TimeoutResult handleTimeout(OrderContext context) {
return TimeoutResult.noAction(); // 终态无超时
}
@Override
public List<OrderAction> getAvailableActions() {
return List.of(OrderAction.APPLY_REFUND, OrderAction.REVIEW);
}
@Override
public void onEnter(OrderContext context, OrderState previousState) {
// 触发积分发放、优惠券发放等
triggerCompletionBenefits(context);
// 启动评价邀请
scheduleReviewReminder(context.getOrderId());
}
}
/**
* 已取消状态:交易终止
*/
@Component
public class CancelledState implements OrderState {
@Override
public OrderStatus getStatus() { return OrderStatus.CANCELLED; }
@Override
public PayResult pay(OrderContext context, PaymentParam param) {
return PayResult.failure("ORDER_CANCELLED", "订单已取消");
}
@Override
public ShipResult ship(OrderContext context, ShipmentParam param) {
return ShipResult.failure("ORDER_CANCELLED", "订单已取消");
}
@Override
public ReceiveResult confirmReceive(OrderContext context) {
return ReceiveResult.failure("ORDER_CANCELLED", "订单已取消");
}
@Override
public CancelResult cancel(OrderContext context, String reason) {
return CancelResult.failure("ORDER_CANCELLED", "订单已取消");
}
@Override
public RefundResult applyRefund(OrderContext context, RefundParam param) {
return RefundResult.failure("ORDER_CANCELLED", "已取消订单无需退款");
}
@Override
public TimeoutResult handleTimeout(OrderContext context) {
return TimeoutResult.noAction();
}
@Override
public List<OrderAction> getAvailableActions() {
return List.of(); // 终态无操作
}
@Override
public void onEnter(OrderContext context, OrderState previousState) {
// 释放库存、清理资源
releaseResources(context);
notifyCancelled(context);
}
}
3.4 状态机可视化与监控
java
/**
* 状态迁移图定义(用于可视化)
*/
@Component
public class StateMachineDefinition {
private final Map<OrderStatus, Set<OrderStatus>> transitions = new HashMap<>();
@PostConstruct
public void init() {
// 定义合法迁移
addTransition(CREATED, PAID, CANCELLED);
addTransition(PAID, SHIPPED, CANCELLED);
addTransition(SHIPPED, COMPLETED, CANCELLED);
addTransition(COMPLETED); // 终态
addTransition(CANCELLED); // 终态
}
private void addTransition(OrderStatus from, OrderStatus... to) {
transitions.put(from, new HashSet<>(Arrays.asList(to)));
}
public boolean isValidTransition(OrderStatus from, OrderStatus to) {
Set<OrderStatus> allowed = transitions.get(from);
return allowed != null && allowed.contains(to);
}
public Set<OrderStatus> getReachableStates(OrderStatus from) {
return transitions.getOrDefault(from, Collections.emptySet());
}
/**
* 生成Mermaid流程图
*/
public String generateMermaidDiagram() {
StringBuilder sb = new StringBuilder("stateDiagram-v2\n");
transitions.forEach((from, toSet) -> {
toSet.forEach(to -> sb.append(" ").append(from).append(" --> ").append(to).append("\n"));
});
return sb.toString();
}
}
/**
* 状态迁移统计
*/
@Component
public class StateTransitionMetrics {
@Autowired private MeterRegistry metrics;
@Autowired private StateTransitionLogRepository repository;
/**
* 计算状态迁移漏斗
*/
public TransitionFunnel calculateFunnel(LocalDate start, LocalDate end) {
Map<OrderStatus, Long> counts = repository.countByStatusAndDateRange(start, end);
long created = counts.getOrDefault(CREATED, 0L);
long paid = counts.getOrDefault(PAID, 0L);
long shipped = counts.getOrDefault(SHIPPED, 0L);
long completed = counts.getOrDefault(COMPLETED, 0L);
long cancelled = counts.getOrDefault(CANCELLED, 0L);
return TransitionFunnel.builder()
.created(created)
.payRate(safeDivide(paid, created))
.shipRate(safeDivide(shipped, paid))
.completeRate(safeDivide(completed, shipped))
.cancelRate(safeDivide(cancelled, created))
.build();
}
/**
* 检测异常迁移路径
*/
public List<AnomalyTransition> detectAnomalies(LocalDateTime since) {
return repository.findRecent(since).stream()
.filter(log -> !stateMachineDefinition.isValidTransition(log.getFromStatus(), log.getToStatus()))
.map(log -> new AnomalyTransition(log.getOrderId(), log.getFromStatus(), log.getToStatus(), log.getTrigger()))
.collect(Collectors.toList());
}
private double safeDivide(long a, long b) {
return b == 0 ? 0 : (double) a / b;
}
}
3.5 工作流引擎中的状态模式扩展
java
/**
* 泛型状态机引擎:支持任意领域对象
*/
public class StateMachine<S extends State<E, C>, E extends Enum<E>, C extends Context<E>> {
private final Class<E> eventType;
private final Map<E, List<Transition<S, E, C>>> transitions = new HashMap<>();
private S currentState;
private final C context;
public StateMachine(C context, S initialState) {
this.context = context;
this.currentState = initialState;
}
/**
* 注册状态迁移
*/
public StateMachine<S, E, C> on(E event) {
transitions.computeIfAbsent(event, k -> new ArrayList<>());
return this;
}
public StateMachine<S, E, C> from(S source) {
transitions.get(currentEvent()).add(new Transition<>(source, null, null));
return this;
}
public StateMachine<S, E, C> to(S target) {
transitions.get(currentEvent()).get(lastIndex()).setTarget(target);
return this;
}
public StateMachine<S, E, C> when(Predicate<C> guard) {
transitions.get(currentEvent()).get(lastIndex()).setGuard(guard);
return this;
}
public StateMachine<S, E, C> perform(Action<S, C> action) {
transitions.get(currentEvent()).get(lastIndex()).setAction(action);
return this;
}
/**
* 触发事件,执行状态迁移
*/
public synchronized boolean fire(E event, Object payload) {
List<Transition<S, E, C>> candidates = transitions.get(event);
if (candidates == null) return false;
for (Transition<S, E, C> t : candidates) {
if (t.getSource() != currentState) continue;
if (t.getGuard() != null && !t.getGuard().test(context)) continue;
// 执行退出动作
currentState.onExit(context, t.getTarget());
// 执行迁移动作
if (t.getAction() != null) {
t.getAction().execute(currentState, context);
}
S oldState = currentState;
currentState = t.getTarget();
// 执行进入动作
currentState.onEnter(context, oldState);
// 记录日志
logTransition(event, oldState, currentState, payload);
return true;
}
return false; // 无匹配迁移
}
public S getCurrentState() { return currentState; }
}
/**
* 审批工作流状态机应用
*/
public class ApprovalWorkflow {
// 状态定义
public enum ApprovalState implements State<ApprovalEvent, ApprovalContext> {
DRAFT {
public void onEnter(ApprovalContext ctx, ApprovalState from) {
ctx.setEditable(true);
}
public List<ApprovalAction> getActions() {
return List.of(SUBMIT, CANCEL);
}
},
PENDING {
public void onEnter(ApprovalContext ctx, ApprovalState from) {
ctx.setEditable(false);
ctx.startTimer();
}
public List<ApprovalAction> getActions() {
return List.of(APPROVE, REJECT, TRANSFER, RECALL);
}
},
APPROVED {
public void onEnter(ApprovalContext ctx, ApprovalState from) {
ctx.completeTimer();
ctx.triggerNextStep();
}
},
REJECTED {
public void onEnter(ApprovalContext ctx, ApprovalState from) {
ctx.completeTimer();
ctx.notifyReject();
}
};
public void onExit(ApprovalContext ctx, ApprovalState to) {}
public void onEnter(ApprovalContext ctx, ApprovalState from) {}
}
// 使用状态机
public StateMachine<ApprovalState, ApprovalEvent, ApprovalContext> createMachine(ApprovalContext ctx) {
return new StateMachine<ApprovalState, ApprovalEvent, ApprovalContext>(ctx, DRAFT)
.on(SUBMIT).from(DRAFT).to(PENDING).when(ctx -> ctx.hasApprover())
.on(APPROVE).from(PENDING).to(APPROVED).perform((state, ctx) -> ctx.recordApproval())
.on(REJECT).from(PENDING).to(REJECTED).perform((state, ctx) -> ctx.recordRejection())
.on(RECALL).from(PENDING).to(DRAFT)
.on(TRANSFER).from(PENDING).to(PENDING).perform((state, ctx) -> ctx.transferApprover());
}
}
四、状态模式与相关模式辨析
| 维度 | 状态模式 | 策略模式 | 职责链模式 |
|---|---|---|---|
| 核心意图 | 状态驱动行为变化 | 算法族可互换 | 请求沿链传递 |
| 状态感知 | 状态自身管理迁移 | 客户端选择策略 | 无状态概念 |
| 行为归属 | 状态对象拥有行为 | 策略对象拥有算法 | 处理器拥有职责 |
| 结构相似性 | 类图结构相似 | 类图结构相似 | 链式结构 |
| 关键区别 | 状态自迁移 | 客户端切换 | 链上传递 |
状态模式 vs 策略模式:两者类图几乎相同,但意图迥异。策略模式由客户端主动选择策略,状态模式由状态对象根据内部条件自动迁移。策略模式是"多选一",状态模式是"生命周期演进"。
五、设计陷阱与规避策略
陷阱一:状态类膨胀 → 提取公共行为到抽象基类,使用组合而非继承复用逻辑。
陷阱二:状态迁移分散 → 统一迁移入口,使用状态机定义校验合法性,记录完整迁移日志。
陷阱三:并发状态冲突 → 状态迁移加分布式锁,使用乐观锁版本控制,设计冲突解决策略。
陷阱四:持久化状态不一致 → 采用事件溯源,状态变更先持久化事件再更新视图,确保最终一致。
六、结语
状态模式的精髓在于将隐式的状态条件判断提升为显式的状态对象结构,使状态成为拥有行为和迁移能力的主动实体。在订单生命周期、审批工作流、游戏AI、设备控制等场景中,状态模式是管理复杂状态机的核心架构工具。掌握状态封装、迁移控制、事件钩子、可视化监控等高级形态,警惕状态膨胀、迁移分散、并发冲突等工程陷阱,是构建可维护状态系统的关键能力。