定义
允许一个对象在其内部状态改变时改变它的行为。从而使对象看起来似乎修改了其行为。
应用场景
- 在软件构建过程中,某些对象的状态如果改变,其行为也会随之,而发生变化,比如文档处于只读状态,其支持的行为和读写状态支持的行为就可能完全不同。
- 如何在运行时根据对象的状态来透明地更改对象的行为?而不会为对象操作和状态转化之间引入紧耦合?
结构
代码示例
//State.h
/****************************************************/
#ifndef STATE_H
#define STATE_H
#include <iostream>
using namespace std;
class Lamp;
// 抽象状态类
class State
{
public:
// 析构函数
virtual ~State() {}
// 操作函数
virtual void handle(Lamp& context) = 0;
};
// 具体状态类-开
class StateOn : public State
{
public:
// 操作函数
virtual void handle(Lamp& context);
};
// 具体状态类-关
class StateOff : public State
{
public:
// 操作函数
virtual void handle(Lamp& context);
};
// 灯
class Lamp
{
public:
// 构造函数,默认状态关闭
Lamp() : m_state(new StateOff()){}
// 析构函数
~Lamp();
// 设置状态
void setState(State* state);
// 请求
void request();
private:
State* m_state;
};
// 操作函数
void StateOn::handle(Lamp& context) {
cout << "当前状态:打开" << endl;
cout << "执行操作:关闭" << endl;
context.setState(new StateOff());
}
// 操作函数
void StateOff::handle(Lamp& context) {
cout << "当前状态:关闭" << endl;
cout << "执行操作:打开" << endl;
context.setState(new StateOn());
}
// 析构函数
Lamp::~Lamp() {
if (m_state) {
delete m_state;
m_state = nullptr;
}
}
// 设置状态
void Lamp::setState(State* state) {
if (m_state) {
delete m_state;
m_state = nullptr;
}
m_state = state;
}
// 请求
void Lamp::request() {
m_state->handle(*this);
}
#endif
//test.cpp
/****************************************************/
#include "State.h"
int main()
{
Lamp lamp;
lamp.request(); // 操作灯
lamp.request(); // 操作灯
return 0;
}
运行结果
要点总结
- State模式将所有与一个特定状态相关的行为都放入一个State的子类对象中,在对象状态切换时,切换相应的对象;但同时维持State的接口,这样实现了具体操作与状态转换之间的解耦。
- 为不同的状态引入不同的对象使得状态转换变得更加明确,而且可以保证不会出现状态不一致的情况,因为转换是原子性的——即要么彻底转换过来,要么不转换。
- 如果State对象没有实例变量,那么各个上下文可以共享同一个State对象,从而节省对象开销。