在很多情况下,一个对象的行为取决于一个或多个动态变化的属性,这样的属性叫做状态,这样的对象叫做有状态的(stateful)对象。
模式定义
当一个对象的内在状态改变时,允许其改变行为(不同的状态,做不同的事)。
状态模式主要解决的是 : 当控制一个对象状态转换的条件表达式过于复杂时的情况。把状态的判断逻辑,转移到表示不同状态的一系列类当中,可以把复杂的判断逻辑简化。
UML图如下:
示例
人假设有两种状态:正常状态 和 非正常状态(生病了)。
参考代码如下:
头文件:
#ifndef _State_H_
#define _State_H_
class Human;
class State;
// 状态基类
class State {
public:
/* 不同的状态,不同的表现 */
virtual void handle(Human * con) = 0;
};
// 精神状态好,正常
class State_Normal : public State {
public:
virtual void handle(Human * con);
};
// 不正常状态
class State_Abnormal : public State {
public:
virtual void handle(Human * con);
};
// 有两种状态的人
class Human{
public:
Human(State * state = nullptr);
void setState(State * state); //设置初始状态
void request(); //切换状态
private:
State * m_state;
};
#endif
实现cpp:
#include <iostream>
using namespace std;
void State_Normal::handle(Human * con){
/* 根据当前状态作出反应 */
cout << " 正常的状态下 做正常的事" << endl;
/* 设置下一状态 */
con->setState(new State_Abnormal);
}
void State_Abnormal::handle(Human * con){
cout << " 生病了,就躺着" << endl;
//改变 人的状态
con->setState(new State_Normal);
}
Human::Human(State * state){
m_state = state;
}
void Human::setState(State * state){
if (state == nullptr)
return;
if ( m_state != nullptr )
{
delete m_state;
m_state = nullptr;
}
m_state = state;
}
void Human::request(){
if(m_state == nullptr )
return;
m_state->handle(this);
}
测试代码:
int main()
{
Human * cont = new Human(new State_Normal);
cont->request();
cont->request();
cont->request();
cont->request();
cont->request();
cont->request();
return 0;
}
结果如下:
小结
- 状态模式,将与特定状态相关的行为都放入一个对象中,由于所有与状态相关的代码都存在于某个具体的状态中,所以通过定义新的State子类可以很容易的增加新的状态和转换。
- 状态模式 可以消除庞大的条件分支语句,大的分支判断会使得难以修改和扩展。