状态模式(State):
当一个对象的内在状态改变时允许改变其行为,这个对象看起来就是改变了其类。
状态模式主要解决的是当控制一个对象状态转换的条件表达式过于复杂的情况。把状态的判断逻辑转移到表示不同状态的一系列类当中,可以把复杂的逻辑简化。
1.将特定的状态相关的行为都放入一个对象中,由于所有与状态相关的代码都存在于某个ConcreteState中,所以通过定义新的子类可以很容易地增加新的状态和转换。
2.这样做的目的就是为了消除庞大的条件分支语句,大的分支判断会使得它们难于修改和扩展,就像我们最早说的刻板印刷一样,任何改动和变化都是致命的,状态模式通过把各种状态转移逻辑分布到State的子类之间,来减少相互的依赖,好比把整个版面改成了一个有一个活字这样就容易维护和扩展了。
3.当一个对象的行为取决于它的状态,并且它必须在运行时刻根据状态改变它们的行为时,就可以考虑使用状态模式了。
接下来实现两套,一个是基本的代码实现一下上上面URL所说的,然后再实现一个根据时间为线索的状态模式,方便加深理解。
状态模式基本实现代码:
#pragma once
#include<queue>
#include<iostream>
using namespace std;
class CContext;
//State类,抽象状态类,定义一个接口以封装与Context的一个特定状态相关的行为。
class CState
{
public:
virtual void Handle(CContext *pContext) = 0;
};
//Context类,维护一个ConcreteState子类的实例,这个实例定义当前的状态。
class CContext
{
private:
CState *m_pState;
queue<CState *>m_qHashMemory;
public:
CContext(CState *pState)
{
while(!m_qHashMemory.empty())
{
m_qHashMemory.pop();
}
m_pState = pState;
m_qHashMemory.push(m_pState);
}
~CContext()
{
while(!m_qHashMemory.empty())
{
delete m_qHashMemory.front();
m_qHashMemory.pop();
}
}
void SetContext(CState *pState)
{
m_pState = pState;
m_qHashMemory.push(m_pState);
}
void Request()
{
m_pState->Handle(this);
}
};
//ConcreteState类,具体状态,每一个子类实现一个与Context的一个状态相关的行为。
class CConcreteStateC : public CState
{
public:
void Handle(CContext *pContext)
{
cout<<"over"<<endl;
return ;
}
};
class CConcreteStateB : public CState
{
public:
void Handle(CContext *pContext)
{
pContext->SetContext(new CConcreteStateC());
pContext->Request();
}
};
class CConcreteStateA : public CState
{
public:
void Handle(CContext *pContext)
{
pContext->SetContext(new CConcreteStateB());
pContext->Request();
}
};
客户端调用代码:
#include "stdafx.h"
#include "StateMode.h"
#include <windows.h>
using namespace std;
int main()
{
CContext *pContext = new CContext(new CConcreteStateA());
pContext->Request();
delete pContext;
return 0;
}
运行结果:
上面就是基本实现了下状态模式的结构,但是感觉没表达清晰,接下来就实现以下一天的工作状态,以时间为状态。
状态模式实现代码:
#pragma once
#include<queue>
#include<iostream>
using namespace std;
class CWork;
//抽象状态
class CState
{
public:
virtual void WriteProgram(CWork *pW) = 0;
};
//工作
class CWork
{
private:
CState *m_pCurrent;
queue<CState *>m_qHashMemory;
public:
double m_fHour;
bool m_bFinish;
CWork()
{
m_pCurrent = NULL;
m_fHour = 0;
m_bFinish = false;
while(!m_qHashMemory.empty())
{
m_qHashMemory.pop();
}
}
~CWork()
{
while(!m_qHashMemory.empty())
{
delete m_qHashMemory.front();
m_qHashMemory.pop();
}
}
void SetState(CState * pCurrent)
{
m_pCurrent = pCurrent;
m_qHashMemory.push(pCurrent);
}
void WriteProgram()
{
m_pCurrent->WriteProgram(this);
}
};
//睡了
class CSleepingState : public CState
{
public:
void WriteProgram(CWork *pW)
{
cout<<"当前时间"<<pW->m_fHour<<"睡着了"<<endl;
}
};
//下班
class CRestState : public CState
{
public:
void WriteProgram(CWork *pW)
{
cout<<"当前时间"<<pW->m_fHour<<"下班回家"<<endl;
}
};
//晚上
class CEveningState : public CState
{
public:
void WriteProgram(CWork *pW)
{
if(pW->m_bFinish)
{
pW->SetState(new CRestState());
pW->WriteProgram();
}
else
{
if(pW->m_fHour < 21)
{
cout<<"当前时间"<<pW->m_fHour<<"加班中"<<endl;
}
else
{
pW->SetState(new CSleepingState());
pW->WriteProgram();
}
}
}
};
//下午
class CAfternoonState : public CState
{
public:
void WriteProgram(CWork *pW)
{
if(pW->m_fHour < 17)
{
cout<<"当前时间"<<pW->m_fHour<<"点 下午了"<<endl;
}
else
{
pW->SetState(new CEveningState());
pW->WriteProgram();
}
}
};
//中午
class CNoonState : public CState
{
public:
void WriteProgram(CWork *pW)
{
if(pW->m_fHour < 13)
{
cout<<"当前时间"<<pW->m_fHour<<"点 中午 饿了"<<endl;
}
else
{
pW->SetState(new CAfternoonState());
pW->WriteProgram();
}
}
};
//上午
class CForenoonState : public CState
{
public:
void WriteProgram(CWork *pW)
{
if(pW->m_fHour < 12)
{
cout<<"当前时间"<<pW->m_fHour<<"点 上午工作,精神百倍"<<endl;
}
else
{
pW->SetState(new CNoonState());
pW->WriteProgram();
}
}
};
客户端调用:
#include "stdafx.h"
#include "StateMode.h"
#include <windows.h>
using namespace std;
int main()
{
CWork *pWork = new CWork();
pWork->SetState(new CForenoonState());
pWork->m_fHour = 9;
pWork->WriteProgram();
pWork->m_fHour = 10;
pWork->WriteProgram();
pWork->m_fHour = 12;
pWork->WriteProgram();
pWork->m_fHour = 13;
pWork->WriteProgram();
pWork->m_fHour = 14;
pWork->WriteProgram();
pWork->m_fHour = 18;
pWork->WriteProgram();
pWork->m_bFinish = true;
pWork->SetState(new CForenoonState());
pWork->m_fHour = 18;
pWork->WriteProgram();
delete pWork;
return 0;
}
运行结果: