设计模式之状态模式-看看状态怎么样?
状态模式
一、状态模式的概念
状态模式属于行为型设计模式,它通过改变对象的内部状态而改变对象的行为,这个对象表现得就好像修改了它的类一样。
状态模式主要解决:当控制一个对象状态转换的条件表达式过于复杂时,把状态的判断逻辑转移到表现不同状态的一系列类当中,从而使复杂的判断逻辑简单化。
二、状态模式使用场景
1、行为随状态改变而改变的场景。
2、条件和分支语句的替代者。
三、状态模式构建方法
1、用户对象(上下文环境)类(Context)
拥有一个状态类型的成员,以标识对象的当前状态,并提供给客户端调用的接口。
2、抽象状态类(State)
封装与用户对象的特定状态相关行为的接口和方法。
3、具体状态类(ConcreteState)
实现抽象状态类定义的接口和方法。
四、状态模式的示例
// StatePattern.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <iostream>
#include <string>
#define DELETE_PTR(p) {if(p!=nullptr){delete (p); (p)=nullptr;}}
using namespace std;
// 根据时间点不同模仿一个人吃早饭、午饭、晚饭的状态,其他时间状态都设置在工作
class EatMeal;
//class MorningTimeState;
//class NoonTimeState;
//class NightTimeState;
// 抽象状态类(State)
class TimeState
{
public:
virtual void changeTimeState(int timeState) = 0;
virtual void toEatMeal(EatMeal *pEatMeal) = 0;
};
// 用户对象(上下文环境)类(Context)-去吃饭
class EatMeal
{
public:
EatMeal()
{
m_curTimeState = nullptr;
}
~EatMeal()
{
DELETE_PTR(m_curTimeState);
}
void changeTimeState(int timeState)
{
m_timeState = timeState;
}
int getCurTime()
{
return m_timeState;
}
void setTimeState(TimeState *pCurTimeState)
{
m_curTimeState = pCurTimeState;
}
TimeState *getTimeState()
{
return m_curTimeState;
}
void toEatMeal()
{
m_curTimeState->toEatMeal(this);
}
private:
int m_timeState;
TimeState *m_curTimeState;
};
// 具体状态类(ConcreteState)-吃早饭
class MorningTimeState : public TimeState
{
public:
void changeTimeState(int timeState)
{
m_timeState = timeState;
}
virtual void toEatMeal(EatMeal *pEatMeal);
private:
int m_timeState;
};
// 具体状态类(ConcreteState)-吃午饭
class NoonTimeState : public TimeState
{
public:
void changeTimeState(int timeState)
{
m_timeState = timeState;
}
virtual void toEatMeal(EatMeal *pEatMeal);
private:
int m_timeState;
};
// 具体状态类(ConcreteState)- 吃晚饭
class NightTimeState : public TimeState
{
public:
void changeTimeState(int timeState)
{
m_timeState = timeState;
}
virtual void toEatMeal(EatMeal *pEatMeal);
private:
int m_timeState;
};
/*因为MorningTimeState、NoonTimeState、NightTimeState三个类中互相调用了类中的方法,
即使前置声明这三个类也不行,类的声明和实现必须分离才行,不分离的话会提示“使用了未定义的类型错误”*/
void MorningTimeState::toEatMeal(EatMeal *pEatMeal)
{
if (pEatMeal->getCurTime() >= 7 && pEatMeal->getCurTime() <= 8) // 早饭
{
cout << "ISMILELI------------>洗刷完了,我要去吃早饭啦!" << endl;
}
else if(pEatMeal->getCurTime() >= 12 && pEatMeal->getCurTime() <= 13) // 下一个吃饭节点午饭
{
MorningTimeState *pMorningTimeState = dynamic_cast<MorningTimeState*>(pEatMeal->getTimeState());
DELETE_PTR(pMorningTimeState);
TimeState *pNoonTimeState = dynamic_cast<TimeState*>(new NoonTimeState);
pEatMeal->setTimeState(pNoonTimeState);
pEatMeal->getTimeState()->toEatMeal(pEatMeal);
}
else // 其他时间都在工作
{
cout << "ISMILELI------------>我是工作狂,我不爱睡觉,除了吃饭就是工作!" << endl;
}
}
void NoonTimeState::toEatMeal(EatMeal *pEatMeal)
{
if (pEatMeal->getCurTime() >= 12 && pEatMeal->getCurTime() <= 13) // 午饭
{
cout << "ISMILELI------------>中午到了,我要去吃午饭啦!" << endl;
}
else if(pEatMeal->getCurTime() >= 18 && pEatMeal->getCurTime() <= 20)// 下一个吃饭节点晚饭
{
NoonTimeState *pNoonTimeState = dynamic_cast<NoonTimeState*>(pEatMeal->getTimeState());
DELETE_PTR(pNoonTimeState);
TimeState *pNightTimeState = dynamic_cast<TimeState*>(new NightTimeState);
pEatMeal->setTimeState(pNightTimeState);
pEatMeal->getTimeState()->toEatMeal(pEatMeal);
}
else // 其他时间都在工作
{
cout << "ISMILELI------------>我是工作狂,我不爱睡觉,除了吃饭就是工作!" << endl;
}
}
void NightTimeState::toEatMeal(EatMeal *pEatMeal)
{
if (pEatMeal->getCurTime() >= 18 && pEatMeal->getCurTime() <= 20) // 晚饭
{
cout << "ISMILELI------------>下班时间到了,我要去吃晚饭啦!" << endl;
}
else if(pEatMeal->getCurTime() >= 7 && pEatMeal->getCurTime() <= 8)// 下一个吃饭节点早饭
{
NightTimeState *pNightTimeState = dynamic_cast<NightTimeState*>(pEatMeal->getTimeState());
DELETE_PTR(pNightTimeState);
TimeState *pMorningTimeState = dynamic_cast<TimeState*>(new MorningTimeState);
pEatMeal->setTimeState(pMorningTimeState);
pEatMeal->getTimeState()->toEatMeal(pEatMeal);
}
else // 其他时间都在工作
{
cout << "ISMILELI------------>我是工作狂,我不爱睡觉,除了吃饭就是工作!" << endl;
}
}
int main()
{
cout << "----------------------状态模式----------------------" << endl;
EatMeal *pEatMeal = new EatMeal;
TimeState *pCurTimeState = dynamic_cast<TimeState*>(new MorningTimeState);
pEatMeal->setTimeState(pCurTimeState);
pEatMeal->changeTimeState(7);
pEatMeal->toEatMeal();
pEatMeal->changeTimeState(13);
pEatMeal->toEatMeal();
pEatMeal->changeTimeState(18);
pEatMeal->toEatMeal();
pEatMeal->changeTimeState(21);
pEatMeal->toEatMeal();
// 指针pCurTimeState内存释放在pEatMeal析构函数中
DELETE_PTR(pEatMeal);
std::cout << "Hello World!\n";
getchar();
}
运行结果:
五、状态模式的优缺点
优点:
1、把复杂的对象状态判断简单化。
2、将所有与某个状态有关的行为放到一个类中,可以方便地增加新的状态,只需要改变对象状态即可改变对象的行为。
3、允许状态转换逻辑与状态对象合成一体,从而简化逻辑判断。
4、多个环境对象可以共享一个状态对象,减少系统中对象的个数。
缺点:
1、每增加一种状态都会增加一个类。
2、状态模式的结构与实现都较为复杂。
3、耦合性强,增加新的状态类需要修改负责状态转换的源代码。
能力有限,如有错误,多多指教。。。
本文为博主原创文章,未经博主允许请勿转载!作者:ISmileLi