// state.cpp
#include <stdio.h>
#ifdef _X_RELEASE_
#define TRACE(str)
#else
#define TRACE(str) printf("%s/n", str)
#endif
class CContext; // CContext在CState有用到,要在此提前声明。
// 注意类CContext的定义一定要放在CState类的实现之前,否则会有下列编译错误:
/*
state.cpp: In member function 'void CState::ChangeState(CContext*, CState*)':
state.cpp:36: error: invalid use of incomplete type 'struct CContext'
state.cpp:9: error: forward declaration of 'struct CContext'
*/
/*** 类的定义 ***/
class CState
{
public:
CState()
{
TRACE("CState");
}
virtual ~CState()
{
TRACE("~CState");
}
// 状态行为接口,注意该接口有一个CContext类型的参数
// 也可以在这里提供一个缺省的实现
virtual void Handle(CContext* pContext) = 0;
void ChangeState(CContext* pContext, CState* pState);
};
// 具体状态类,实现为单件。注意在该类中只有内存的分配,没有释放
class CConcreteStateA : public CState
{
private:
static CConcreteStateA* m_pStateA;
private:
CConcreteStateA()
{
}
public:
static CConcreteStateA* Instance()
{
if (!m_pStateA)
{
m_pStateA = new CConcreteStateA();
}
return m_pStateA;
}
public:
virtual void Handle(CContext* pContext);
};
// 具体状态类,实现为单件。注意在该类中只有内存的分配,没有释放
class CConcreteStateB : public CState
{
private:
static CConcreteStateB* m_pStateB;
private:
CConcreteStateB()
{
}
public:
static CConcreteStateB* Instance()
{
if (!m_pStateB)
{
m_pStateB = new CConcreteStateB();
}
return m_pStateB;
}
public:
virtual void Handle(CContext* pContext);
};
class CContext
{
private:
CState* m_pState; // 当前状态
private:
friend void CState::ChangeState(CContext* pContext, CState* pState);
void ChangeState(CState* pState) // 改变当前状态
{
TRACE("CContext::ChangeState");
m_pState = pState;
}
public:
CContext()
{
TRACE("CContext");
// 假设初始状态为CConcreteStateA,当然初始状态也可以作为构造函数的参数传入
m_pState = CConcreteStateA::Instance();
}
virtual ~CContext()
{
TRACE("~CContext");
m_pState = 0;
}
void Request()
{
TRACE("Request");
if (m_pState)
{
m_pState->Handle(this); // 调用状态行为接口
}
}
};
/*** 类的实现 ***/
void CState::ChangeState(CContext* pContext, CState* pState)
{
TRACE("CState::ChangeState");
// 调用CContext类的ChangeState函数进行状态转换
pContext->ChangeState(pState);
}
CConcreteStateA* CConcreteStateA::m_pStateA = 0;
void CConcreteStateA::Handle(CContext* pContext)
{
TRACE("CConcreteStateA::Handle");
ChangeState(pContext, CConcreteStateB::Instance());
}
CConcreteStateB* CConcreteStateB::m_pStateB = 0;
void CConcreteStateB::Handle(CContext* pContext)
{
TRACE("CConcreteStateB::Handle");
ChangeState(pContext, CConcreteStateA::Instance());
}
int main()
{
CContext* pContext = new CContext();
pContext->Request();
TRACE("-----");
pContext->Request();
TRACE("-----");
pContext->Request();
TRACE("-----");
delete pContext;
pContext = 0;
return 0;
}
/*
root@ubuntu:/home/hgc/test# g++ state.cpp -o state -g -Wall
root@ubuntu:/home/hgc/test# ./state
CContext
CState
Request
CConcreteStateA::Handle
CState
CState::ChangeState
CContext::ChangeState
-----
Request
CConcreteStateB::Handle
CState::ChangeState
CContext::ChangeState
-----
Request
CConcreteStateA::Handle
CState::ChangeState
CContext::ChangeState
-----
~CContext
*/