State 状态模式:允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类。也称为状态对象(Objects for States)。
GOF 用 TCP 连接说明 State 模式,很清晰:考虑一个表示网络连接的类 TCPConnection。一个 TCPConnection 对象的状态处于若干不同状态之一:连接已建立(Established)。正在监听(Listening)、连接已关闭(Closed)。当一个 TCPConnection 对象收到其它对象的请求时,它根据自身的当前状态作出不同的反应。例如,一个 Open 请求的结果依赖于连接是否处于连接已关闭状态还是连接已建立状态。State模式描述了 TCPConnection 如何在每一种状态下表现出不同的行为。
这一模式的关键思想是引入一个称为 TCPState 的抽象类来表示网络的连接状态。TCPState 类为各表示不同的操作状态的子类声明了一个公共接口。TCPState 的子类实现与特定状态相关行为。例如,TCPEstablished 和 TCPClosed 类分别实现了特定于 TCPConnection 连接已建立和边境已关闭的行为。TCPConnection 类维护一个表示 TCP 连接当前状态的对象(一个 TCPState 子类的实例)。TCPConnection 类将所有与状态相关的请求委托给这个状态对象。TCPConnection 使用它的 TCPState 子类实例来执行特定于连接状态的操作。一旦连接状态改变,TCPConnection 对象就会改变它所使用的状态对象。例如当连接从已建立状态转为已关闭状态时,TCPConnection 会用一个 TCPClosed 的实例来代替原来的 TCPEstablised 的实例。如下图所示:
State 状态模式适用于:
1.一个对象的行为取决于它的状态,并用它必须在运行时刻根据状态改变它的行为。
2.一个操作中含有庞大的多分支的条件语句,且这些分支依赖于该对象的状态。这个状态通常用一个或多个枚举常量表示。通常,有多个操作包含这一相同的条件语句。State 模式将每一个条件分支放入一个独立的类中。这使得可以根据对象自身的情况将对象的状态作为一个对象,这一对象可以不依赖于其它对象而独立变化。
State 状态模式的通用结构如下图:
参与者:
Context:环境,定义客户感兴趣的接口。维护一个 ConcreteState 子类的实例,这个实例定义当前状态。
State:状态,定义一个接口以封装与 Context 的一个特定状态相关的行为。
ConcreteState:具体状态子类,每一个子类实现一个与 Context 的一个状态相关的行为。
Context 将与状态相关的请求委托给当前的 ConcreteState 对象处理;Context 可将自身作为一个参数传递给处理该请求的状态对象,这使得状态对象在必要时可访问 Context;Context 是客户使用的主要接口,客户可用状态对象来配置一个 Context,一旦一个 Context 配置完毕,它的客户不再需要直接与状态对象打交道;Context 或 ConcreteState 子类都可以决定哪个状态是另外哪一个的后继者,以及是在何种条件下进行状态转换。
State 状态模式代码示例:
1: //State.h
2:
3: #pragma once
4: class State;
5:
6: //Context 定义客户感兴趣的接口
7: class Context
8: {
9: public:
10: Context(State* pState);
11: ~Context();
12: void Request();
13: void ChangeState(State *pState);
14: private:
15: //Context 维护一个 State 的实例
16: //该实例定义当前状态
17: State *m_pState;
18: };
19:
20: //状态,定义一个接口以封装与 Context 的一个特定状态相关的行为
21: class State
22: {
23: public:
24: virtual ~State(){}
25: virtual void Handle(Context* pContext) = 0;
26: };
27:
28: //具体的状态子类, 每一个子类实现与 Context 的一个状态相关的行为
29: //Context 可将自身相关的请求委托给当前的 ConcreteState 对象处理
30: class ConcreateStateA : public State
31: {
32: public:
33: void Handle(Context* pContext);
34: };
35:
36: class ConcreateStateB : public State
37: {
38: public:
39: void Handle(Context* pContext);
40: };
1:
2: #include "State.h"
3: #include
4:
5: Context::Context(State* pState)
6: : m_pState(pState){ }
7:
8: Context::~Context()
9: {
10: delete m_pState;
11: m_pState = NULL;
12: }
13:
14: void Context::Request()
15: {
16: if (NULL != m_pState)
17: {
18: m_pState->Handle(this);
19: }
20: }
21: //改变状态
22: void Context::ChangeState(State *pState)
23: {
24: if (NULL != m_pState)
25: {
26: delete m_pState;
27: m_pState = NULL;
28: }
29: //用新的状态实例进行替换
30: m_pState = pState;
31: }
32:
33: /////
34: void ConcreateStateA::Handle(Context* pContext)
35: {
36: std::cout << "Handle by ConcreateStateA" << std::endl;
37: if (NULL != pContext)
38: {
39: pContext->ChangeState(new ConcreateStateB());
40: }
41: }
42:
43: void ConcreateStateB::Handle(Context* pContext)
44: {
45: std::cout << "Handle by ConcreateStateB" << std::endl;
46:
47: if (NULL != pContext)
48: {
49: pContext->ChangeState(new ConcreateStateA());
50: }
51: }
1:
2: #include "State.h"
3: #include
4:
5: int main()
6: {
7: State *pState = new ConcreateStateA();
8: Context *pContext = new Context(pState);
9: pContext->Request();
10: pContext->Request();
11: pContext->Request();
12:
13: delete pContext;
14:
15: return EXIT_SUCCESS;
16: }