状态模式入门

状态模式将状态封装成为独立的类, 并将动作传递给当前的状态对象. 通过这种方式允许对象在内部状态改变时同时改变其行为, 即调用相同的对象方法, 但是对象会根据内部状态不同执行不同的行为.

状态模式的优点:

  • 结构清晰, 避免了过多的if或switch判断语句, 降低了代码复杂度, 提高了系统可维护性
  • 可以让多个环境对象共享一个状态对象,从而减少系统中对象的个数
  • 封装了状态转换规则

状态模式的缺点:

  • 状态模式的使用必然会增加系统类和对象的个数
  • 状态模式的结构与实现都较为复杂,如果使用不当将导致程序结构和代码的混乱

UML类图

代码示例

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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
/*
一个简单的订单系统包含以下(动作)状态:
 (买家下单->)待付款
 (买家付款->)待发货
 (卖家发货->)待确认收货
 (买家确认收货->) 已完成
 (买家删除订单记录->) 订单不存在
*/


/// 订单状态接口, 接口内的方法代表可能发生的动作
protocol OrderState {

/// 下单
func placeOrder()

/// 付款
func payOrder()

/// 发货
func deliver()

/// 确认收货
func confirmReceipt()

/// 删除订单
func deleteOrder()
}


/// 订单上下文, 管理订单状态
class OrderContext {
lazy var noOrderState: OrderState = NoOrder(orderContext: self)
lazy var waitingForPaymentState: OrderState = WaitingForPayment(orderContext: self)
lazy var waitingForDeliverState: OrderState = WaitingForDeliver(orderContext: self)
lazy var waitingForConfirmState: OrderState = WaitingForConfirm(orderContext:self)
lazy var orderCompletedState: OrderState = OrderCompleted(orderContext: self)

/// 初始状态, 无订单
lazy var currentState: OrderState = noOrderState

/// 订单操作
func placeOrder() {
currentState.placeOrder()
}

func payOrder() {
currentState.payOrder()
}

func deliver() {
currentState.deliver()
}

func confirmReceipt() {
currentState.confirmReceipt()
}
func deleteOrder() {
currentState.deleteOrder()
}

}

/// 初始状态, 订单不存在
class NoOrder: OrderState {
var orderContext: OrderContext
init(orderContext: OrderContext) {
self.orderContext = orderContext
}

func placeOrder() {
print("用户下单, 生成订单")
print("订单状态: 等待付款")
orderContext.currentState = orderContext.waitingForPaymentState
}

func payOrder() {
print("订单不存在, 不能支付")
}

func deliver() {
print("订单不存在, 不能发货")
}

func confirmReceipt() {
print("订单不存在, 不能确认收货")
}

func deleteOrder() {
print("订单不存在, 不能删除")
}
}

/// 等待付款状态
class WaitingForPayment: OrderState {

var orderContext: OrderContext
init(orderContext: OrderContext) {
self.orderContext = orderContext
}

func placeOrder() {
print("订单已存在, 不能重复下单")
}

func payOrder() {
print("订单已支付")
print("订单状态: 等待发货")
orderContext.currentState = orderContext.waitingForDeliverState
}

func deliver() {
print("订单尚未支付, 不能发货")
}

func confirmReceipt() {
print("订单尚未支付, 不能确认收货")
}
func deleteOrder() {
print("交易未完成, 无法删除")
}
}

/// 等待发货状态
class WaitingForDeliver: OrderState {
var orderContext: OrderContext
init(orderContext: OrderContext) {
self.orderContext = orderContext
}

func placeOrder() {
print("订单已存在, 不能重复下单")
}

func payOrder() {
print("订单已支付, 不能重复支付")
}

func deliver() {
print("订单已发货")
print("订单状态: 等待确认收货")
orderContext.currentState = orderContext.waitingForConfirmState
}

func confirmReceipt() {
print("订单尚未发货, 不能确认收货")
}

func deleteOrder() {
print("交易未完成, 无法删除")
}
}

/// 等待确认收货
class WaitingForConfirm: OrderState {
var orderContext: OrderContext
init(orderContext: OrderContext) {
self.orderContext = orderContext
}

func placeOrder() {
print("订单已存在, 不能重复下单")
}

func payOrder() {
print("订单已支付, 不能重复支付")
}

func deliver() {
print("订单已发货, 不能再次发货")
}

func confirmReceipt() {
print("订单已确认收货, 交易完成")
orderContext.currentState = orderContext.orderCompletedState
}

func deleteOrder() {
print("交易未完成, 无法删除")
}
}

/// 订单已完成
class OrderCompleted: OrderState {
var orderContext: OrderContext
init(orderContext: OrderContext) {
self.orderContext = orderContext
}

func placeOrder() {
print("订单已完成, 不能重复下单")
}

func payOrder() {
print("订单已完成, 不能重复支付")
}

func deliver() {
print("订单已完成, 不能再次发货")
}

func confirmReceipt() {
print("订单已完成, 不能再次确认收货")
}

func deleteOrder() {
print("交易完成, 删除订单")
orderContext.currentState = orderContext.noOrderState
}
}

客户端调用:

1
2
3
4
5
6
7
8
9
orderContext.placeOrder()

orderContext.payOrder()

orderContext.deliver()

orderContext.confirmReceipt()

orderContext.deleteOrder()

扩展阅读