目录

一、定义
1.1 什么是状态模式?
状态模式(State Pattern) 是一种 行为型 设计模式,对有状态的对象,把复杂的 "判断逻辑" 提取到不同的状态对象中,允许状态对象在其内部状态发生改变时,改变其行为。
1.2 状态模式的优缺点
状态模式的优点:
- 结构清晰 :状态模式将与特定状态相关的行为局部化道一个状态中,并且将不同状态的行为分割开来,满足 "但一职责原则"。
- 将状态转换显示化:减少对象间的相互依赖,将不同的状态引入独立的对象中会是的状态转换变得更加明确,且减少对相见的相互依赖。
- 状态类职责明确:有利于程序的扩展。通过定义新的子类很容易地增加新的状态和转换。
状态模式的缺点:
- 状态模式的使用必然会增加系统的类与对象的个数。
- 状态模式的结构与实现都较为复杂,如果使用不当会导致程序结构和代码的混乱。
- 状态模式对开闭原则的支持并不太好,对于可以切换状态的状态模式,增加新的状态类需要修改那些负责状态转换的源码,否则无法切换到新增状态,而且修改某个状态类的行为也需要修改对应类的源码。
1.3 状态模式的实现结构
状态模式把受环境改变的对象行为包装在不同的状态对象里,其意图是让一个对象在其内部状态改变的时候,其行为也随之改变。现在我们来分析其基本结构和实现方法。
状态模式主要包含三个角色:
- Context(环境类):定义客户端感兴趣的接口,维护一个 State 子类的实例,这个示例定义当前状态。
- State(抽象状态类):定义一个接口,用以封装 Context 的特定状态相关的行为。
- ConcreteState(具体状态类):每一个子类实现一个与 Context 的一个状态相关的行为。
二、适用场景
适用场景一:算法框架固定的场景
- 适用原因:当多个相关类需要执行相同的工作流程或算法骨架,但其中某些具体步骤的实现各不相同。这些类共享一个通用的操作序列,只是在特定环节存在差异化实现。
- 状态模式解决的问题:消除重复的过程控制代码,确保所有子类都遵循相同的执行顺序和流程规范。避免了在每个具体类中重复编写相同的流程控制逻辑,同时也防止了因流程修改需要在多个地方同步更新的维护负担。
适用场景二:代码复用的场景
- 适用原因:系统中存在多个类包含大量相同的行为代码,只有部分核心逻辑存在差异。这些类在整体功能上高度相似,但在关键步骤上需要个性化实现。
- 状态模式解决的问题:通过将公共代码提升到父类中,显著减少代码重复。当公公逻辑需要修改时,只需在父类中修改一处即可影响所有子类,大大提高了代码的可维护性和一致性。
适用场景三:控制子类扩展的场景
- 适用原因:需要确保子类在扩展时不会破坏核心算法的结构,或者需要限制子类只能重写特定的操作步骤。系统要求对扩展行为进行规范化管理。
- 解决的问题:防止子类随意修改关键流程,确保系统的稳定性和一致性。通过模板方法定义不可更改的算法骨架,既保证了扩展的灵活性,又维护了核心流程的稳定性。
三、代码示例:订单状态管理
3.1 背景介绍
在电商系统下,订单状态管理是一个典型的状态模式应用场景。订单会经历从创建到完成的多个状态,每个状态下可执行的操作各不相同。
3.2 问题分析
如果不使用状态模式,我们可能会写出这样的代码:
java
public class Order {
private String state;
public void handle() {
if ("pending".equals(state)) {
System.out.println("订单待支付,可以支付或取消");
} else if ("paid".equals(state)) {
System.out.println("订单已支付,可以发货");
} else if ("shipped".equals(state)) {
System.out.println("订单已发货,等待确认收货");
} else if ("completed".equals(state)) {
System.out.println("订单已取消,不能进行任何操作");
}
}
public void pay() {
if ("pending".equals(state)) {
state = "paid";
System.out.println("支付成功");
} else {
System.out.println("当前状态不能支付");
}
}
}
这种方式的缺点很明显:
- 大量的
if-else语句,代码臃肿; - 违反开闭原则,新增状态需要修改原有代码;
- 状态转换逻辑分散在各个方法中,难以维护;
3.3 状态模式解决方案
代码 UML 如下:
CancelledState +handle(OrderContext) +cancel(OrderContext) +pay(OrderContext) +ship(OrderContext) +confirm(OrderContext) CompletedState +confirm(OrderContext) +cancel(OrderContext) +pay(OrderContext) +handle(OrderContext) +ship(OrderContext) OrderContext +confirm() +handle() +getState() +pay() +setState(OrderState) +getOrderId() +cancel() +ship() <<Interface>> OrderState +pay(OrderContext) +ship(OrderContext) +confirm(OrderContext) +handle(OrderContext) +cancel(OrderContext) PaidState +handle(OrderContext) +ship(OrderContext) +cancel(OrderContext) +confirm(OrderContext) +pay(OrderContext) PendingState +ship(OrderContext) +handle(OrderContext) +confirm(OrderContext) +cancel(OrderContext) +pay(OrderContext) ShippedState +pay(OrderContext) +ship(OrderContext) +confirm(OrderContext) +cancel(OrderContext) +handle(OrderContext) StatePatternDemo +main(String[])
1)定义状态接口
java
/**
* 订单状态接口
*/
public interface OrderState {
void handle(OrderContext context);
void pay(OrderContext context);
void ship(OrderContext context);
void confirm(OrderContext context);
void cancel(OrderContext context);
}
2)实现具体状态类
java
/**
* 待支付状态
*/
public class PendingState implements OrderState {
@Override
public void handle(OrderContext context) {
System.out.println("订单待支付,可以支付或取消");
}
@Override
public void pay(OrderContext context) {
System.out.println("支付成功,订单状态变为已支付");
context.setState(new PaidState());
}
@Override
public void ship(OrderContext context) {
System.out.println("待支付状态不能发货");
}
@Override
public void confirm(OrderContext context) {
System.out.println("待支付状态不能确认收货");
}
@Override
public void cancel(OrderContext context) {
System.out.println("订单已取消");
context.setState(new CancelledState());
}
}
/**
* 已支付状态
*/
public class PaidState implements OrderState {
@Override
public void handle(OrderContext context) {
System.out.println("订单已支付,可以发货或取消");
}
@Override
public void pay(OrderContext context) {
System.out.println("订单已支付,无需重复支付");
}
@Override
public void ship(OrderContext context) {
System.out.println("发货成功,订单状态变为已发货");
context.setState(new ShippedState());
}
@Override
public void confirm(OrderContext context) {
System.out.println("已支付状态不能确认收货");
}
@Override
public void cancel(OrderContext context) {
System.out.println("取消订单,退款处理中");
context.setState(new CancelledState());
}
}
/**
* 已发货状态
*/
public class ShippedState implements OrderState {
@Override
public void handle(OrderContext context) {
System.out.println("订单已发货,等待确认收货");
}
@Override
public void pay(OrderContext context) {
System.out.println("已发货状态不能支付");
}
@Override
public void ship(OrderContext context) {
System.out.println("订单已发货,不能重复发货");
}
@Override
public void confirm(OrderContext context) {
System.out.println("确认收货,订单完成");
context.setState(new CompletedState());
}
@Override
public void cancel(OrderContext context) {
System.out.println("已发货状态不能取消,请联系客服");
}
}
/**
* 已完成状态
*/
public class CompletedState implements OrderState {
@Override
public void handle(OrderContext context) {
System.out.println("订单已完成,可以评价");
}
@Override
public void pay(OrderContext context) {
System.out.println("订单已完成,不能支付");
}
@Override
public void ship(OrderContext context) {
System.out.println("订单已完成,不能发货");
}
@Override
public void confirm(OrderContext context) {
System.out.println("订单已完成,不能重复确认");
}
@Override
public void cancel(OrderContext context) {
System.out.println("订单已完成,不能取消");
}
}
/**
* 已取消状态
*/
public class CancelledState implements OrderState {
@Override
public void handle(OrderContext context) {
System.out.println("订单已取消,不能进行任何操作");
}
@Override
public void pay(OrderContext context) {
System.out.println("订单已取消,不能支付");
}
@Override
public void ship(OrderContext context) {
System.out.println("订单已取消,不能发货");
}
@Override
public void confirm(OrderContext context) {
System.out.println("订单已取消,不能确认收货");
}
@Override
public void cancel(OrderContext context) {
System.out.println("订单已取消,不能重复取消");
}
}
3)定义环境类
java
/**
* 订单上下文类
*/
public class OrderContext {
private OrderState state;
private String orderId;
public OrderContext(String orderId) {
this.orderId = orderId;
// 初始状态为待支付
this.state = new PendingState();
}
public void setState(OrderState state) {
this.state = state;
}
public OrderState getState() {
return state;
}
// 委托给状态对象处理
public void handle() {
state.handle(this);
}
public void pay() {
state.pay(this);
}
public void ship() {
state.ship(this);
}
public void confirm() {
state.confirm(this);
}
public void cancel() {
state.cancel(this);
}
public String getOrderId() {
return orderId;
}
}
4)客户端测试
java
/**
* 测试类
*/
public class StatePatternDemo {
public static void main(String[] args) {
OrderContext order = new OrderContext("ORDER001");
// 初始状态
order.handle();
order.pay();
// 已支付状态
order.handle();
order.ship();
// 已发货状态
order.handle();
order.confirm();
// 已完成状态
order.handle();
order.cancel();
System.out.println("====================================");
// 测试异常流程
OrderContext order2 = new OrderContext("ORDER002");
order2.ship(); // 待支付状态尝试发货
order2.cancel(); // 取消订单
order2.pay(); // 已取消状态尝试支付
}
}
4)测试结果
执行 main() 之后,结果如下所示:

整理完毕,完结撒花~🌻
参考地址:
1.状态模式(State模式),https://blog.csdn.net/qq_35784669/article/details/121238278