下面是一篇关于设计模式之状态模式(State Pattern)的详细博客,并附有 Java 实现代码示例。
深入理解设计模式之:状态模式(State Pattern)
一、什么是状态模式?
状态模式(State Pattern)是一种行为型设计模式。它允许一个对象在其内部状态发生改变时,改变其行为(即表现出不同的行为)。状态模式将与状态相关的行为封装到独立的状态类中,并通过状态切换来改变对象的行为。
核心思想:
将状态的切换和行为的变化解耦,使得状态切换变得灵活,代码结构清晰,易于扩展和维护。
二、状态模式的应用场景
- 对象的行为依赖于它的状态,并且在运行时根据状态发生改变
- 代码中包含大量与状态相关的条件语句(如 if-else 或 switch-case)
- 状态切换频繁,且状态行为复杂
常见例子:
- 工作流引擎(如订单状态:待支付、已支付、已发货、已完成等)
- TCP 连接状态(CLOSED、LISTEN、SYN_SENT、ESTABLISHED 等)
- 游戏角色状态(待机、攻击、防御、死亡等)
三、状态模式的结构
- Context(环境类):持有当前状态对象,负责状态切换
- State(抽象状态):定义所有具体状态的公共接口
- ConcreteState(具体状态):实现具体状态对应的行为
四、UML 类图
+----------------+ +---------------------+
| Context |<>----->| State |
+----------------+ +---------------------+
| state: State | | + handle() |
| + setState() | +---------------------+
| + request() | /_\
+----------------+ |
|
+------------------+------------------+
| |
+---------------------+ +---------------------+
| ConcreteStateA | | ConcreteStateB |
+---------------------+ +---------------------+
| + handle() | | + handle() |
+---------------------+ +---------------------+
五、Java 实现代码示例
1. 抽象状态接口
public interface State {
void handle(Context context);
}
2. 具体状态类
public class StateA implements State {
@Override
public void handle(Context context) {
System.out.println("当前状态:A,切换到状态B");
context.setState(new StateB());
}
}
public class StateB implements State {
@Override
public void handle(Context context) {
System.out.println("当前状态:B,切换到状态A");
context.setState(new StateA());
}
}
3. 环境类
public class Context {
private State state;
public Context(State state) {
this.state = state;
}
public void setState(State state) {
this.state = state;
}
public void request() {
state.handle(this);
}
}
4. 客户端调用
public class Main {
public static void main(String[] args) {
Context context = new Context(new StateA());
context.request(); // 输出:当前状态:A,切换到状态B
context.request(); // 输出:当前状态:B,切换到状态A
context.request(); // 输出:当前状态:A,切换到状态B
}
}
六、实际应用案例:订单状态流转
以电商订单为例,订单有“待支付”、“已支付”、“已发货”、“已完成”四种状态,每种状态下允许的操作不同。
1. 状态接口
public interface OrderState {
void next(OrderContext ctx);
void prev(OrderContext ctx);
String getStatus();
}
2. 具体状态类
public class PendingState implements OrderState {
public void next(OrderContext ctx) {
ctx.setState(new PaidState());
}
public void prev(OrderContext ctx) {
System.out.println("已是初始状态,不能回退");
}
public String getStatus() {
return "待支付";
}
}
public class PaidState implements OrderState {
public void next(OrderContext ctx) {
ctx.setState(new ShippedState());
}
public void prev(OrderContext ctx) {
ctx.setState(new PendingState());
}
public String getStatus() {
return "已支付";
}
}
public class ShippedState implements OrderState {
public void next(OrderContext ctx) {
ctx.setState(new CompletedState());
}
public void prev(OrderContext ctx) {
ctx.setState(new PaidState());
}
public String getStatus() {
return "已发货";
}
}
public class CompletedState implements OrderState {
public void next(OrderContext ctx) {
System.out.println("订单已完成,不能再前进");
}
public void prev(OrderContext ctx) {
ctx.setState(new ShippedState());
}
public String getStatus() {
return "已完成";
}
}
3. 环境类
public class OrderContext {
private OrderState state;
public OrderContext() {
state = new PendingState();
}
public void setState(OrderState state) {
this.state = state;
}
public void next() {
state.next(this);
}
public void prev() {
state.prev(this);
}
public void printStatus() {
System.out.println("当前订单状态:" + state.getStatus());
}
}
4. 客户端调用
public class Main {
public static void main(String[] args) {
OrderContext order = new OrderContext();
order.printStatus(); // 待支付
order.next();
order.printStatus(); // 已支付
order.next();
order.printStatus(); // 已发货
order.next();
order.printStatus(); // 已完成
order.next(); // 订单已完成,不能再前进
order.prev();
order.printStatus(); // 已发货
}
}
七、状态模式的优缺点
优点:
- 状态切换逻辑清晰,易于扩展和维护
- 避免大量 if-else 或 switch-case
- 状态行为封装,符合开闭原则
缺点:
- 状态类数量可能增多
- 结构相对复杂
八、总结
状态模式是处理对象状态切换和行为变化的经典方案,广泛应用于工作流、状态机、游戏开发等场景。掌握状态模式有助于编写灵活、可扩展的代码结构。
建议:
- 当对象行为依赖于状态且状态切换复杂时,优先考虑状态模式
- 状态模式与策略模式、命令模式等常结合使用
如需更多设计模式讲解或源码分析,欢迎留言交流!