C#中的状态模式

当对象需要根据内部状态改变行为时,常见做法:

1
2
3
4
5
switch(currentState) {
case "New": ProcessNew(); break;
case "Shipped": ProcessShipped(); break;
case "Delivered": ProcessDelivered(); break;
}

问题:

  1. 状态转换逻辑散落在各处

  2. 新增状态需修改核心代码

  3. 状态和行为强耦合

解决方案:状态模式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
///<状态模式>

//1. 定义状态接口
public interface IOrderState
{
void Process(OrderStatusManager context);
}
//2. 实现具体状态类
public class NewOrderState : IOrderState
{
public void Process(OrderStatusManager context)
{
Console.WriteLine("Processing new order");
context.SetState(new ShippedOrderState());
}
}
public class ShippedOrderState : IOrderState
{
public void Process(OrderStatusManager context)
{
Console.WriteLine("Processing shipped order");
context.SetState(new DeliveredOrderState());
}
}
public class DeliveredOrderState : IOrderState
{
public void Process(OrderStatusManager context)
{
Console.WriteLine("Processing delivered order");
}
}
//3. 创建状态管理类
public class OrderStatusManager
{
private IOrderState _orederState { get; set; }
public void SetState(IOrderState orderState)
{
_orederState = orderState;
}
public void Process()
{
_orederState.Process(this);
}
}

///<状态模式/>

模式特点

  1. 状态封装

    • 每个状态都是独立类

    • 包含状态特有行为

    • 控制状态转换逻辑

  2. 状态转换

    1
    2
    // 在内部完成状态转换
    context.SetState(new ShippedOrderState());
  3. 上下文委托

    1
    2
    3
    4
    // 行为委托给当前状态
    public void Process() {
    _orederState.Process(this);
    }

    执行流程:

    1
    2
    3
    4
    5
    6
    OrderStatusManager orderStatusManager = new OrderStatusManager();
    orderStatusManager.SetState(new NewOrderState());

    orderStatusManager.Process(); // 输出: Processing new order → 状态变为Shipped
    orderStatusManager.Process(); // 输出: Processing shipped order → 状态变为Delivered
    orderStatusManager.Process(); // 输出: Processing delivered order

设计优势

特性 实现方式 收益
状态隔离 每个状态独立类 修改状态不影响其他逻辑
消除条件分支 多态代替switch 代码更简洁
显式状态转换 SetState()方法 状态流转清晰可见
开闭原则 新增状态只需添加类 扩展性强

适用场景

  • 对象行为随状态改变的场景

  • 状态数量超过5个的复杂状态机

  • 需要清晰状态转换路径的系统

  • 订单流程、游戏角色状态等工作流

状态模式通过将每个状态封装为独立类来管理状态相关行为
上下文对象(OrderStatusManager)持有当前状态引用
状态转换由具体状态类触发
符合单一职责原则(每个状态只关注自身行为)

完整代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
///<状态模式>
public interface IOrderState
{
void Process(OrderStatusManager context);
}

public class NewOrderState : IOrderState
{
public void Process(OrderStatusManager context)
{
Console.WriteLine("Processing new order");
context.SetState(new ShippedOrderState());
}
}
public class ShippedOrderState : IOrderState
{
public void Process(OrderStatusManager context)
{
Console.WriteLine("Processing shipped order");
context.SetState(new DeliveredOrderState());
}
}
public class DeliveredOrderState : IOrderState
{
public void Process(OrderStatusManager context)
{
Console.WriteLine("Processing delivered order");
}
}
public class OrderStatusManager
{
private IOrderState _orederState { get; set; }
public void SetState(IOrderState orderState)
{
_orederState = orderState;
}
public void Process()
{
_orederState.Process(this);
}
}

///<状态模式/>



public class Program
{
public static void Main(string[] args)
{
///<状态模式>
Console.WriteLine();
Console.WriteLine("状态模式:");
OrderStatusManager orderStatusManager = new OrderStatusManager();
orderStatusManager.SetState(new NewOrderState());
orderStatusManager.Process();
orderStatusManager.Process();
orderStatusManager.Process();
///<状态模式/>
}
}