提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
前言
提示:这里可以添加本文要记录的大概内容:
在组件构建过程中,某些对象的状态经常面临变化,如何对这些对象的变化进行有效的管理,同时又维持高层模块的稳定,需要使用状态模式
一、问题场景
某些对象的状态如果发生改变,其行为也会随之发生变化,比如文档处于只读状态,其支持的行为和读写状态支持的行为就可能完全不同,如何根据对象的状态来透明的更改对象的行为,而不会为对象操作和状态之间引入耦合。
如下面代码所示
cpp
enum NetworkState
{
Network_Open,
Network_Close,
Network_Connect
};
class NetworkProcesor
{
NetworkState state;
public:
void Operation1()
{
if (state == Network_Open)
{
// .....
state = Network_Close;
}
else if(state == Network_Close)
{
// .....
state = Network_Open;
}
else if (state == Network_Connect)
{
// .....
state = Network_Open;
}
}
};
这个和之前的策略模式很像,有大量if-else。违背了"开闭原则",对扩展开放,对更改关闭
二、状态模式
NetworkState从enum变成基类,每一个派生类自己管理每一种行为,并且定义好切换状态,且每一个派生类都是单例模式。而NetworkProcesor只是内部存了一个基类指针指向不同的状态类,其内部方法都是调用对应的派生类方法,并且更新指向的派生类对象,因此,NetworkProcesor就不会再更变了。
cpp
class NetworkState
{
public:
NetworkState *pNext;
virtual void Operation1() = 0;
virtual void Operation2() = 0;
virtual void Operation3() = 0;
virtual ~NetworkState() {}
};
class OpenState : public NetworkState
{
static NetworkState *m_instance;
public:
static NetworkState *GetInstance()
{
if (m_instance == nullptr)
{
m_instance = new OpenState();
}
return m_instance;
}
void Operation1()
{
// ********
pNext = CloseState::GetInstance();
}
void Operation2()
{
// ********
pNext = ConnectState::GetInstance();
}
void Operation3()
{
// ********
pNext = WaitState::GetInstance();
}
};
class CloseState : public NetworkState
{
static NetworkState *m_instance;
public:
static NetworkState *GetInstance()
{
if (m_instance == nullptr)
{
m_instance = new CloseState();
}
return m_instance;
}
void Operation1()
{
// ********
pNext = CloseState::GetInstance();
}
void Operation2()
{
// ********
pNext = ConnectState::GetInstance();
}
void Operation3()
{
// ********
pNext = WaitState::GetInstance();
}
};
class NetworkProcesor
{
NetworkState* pstate; // 传入状态对象
public:
NetworkProcesor(NetworkState* pstate)
{
this->pstate = pstate;
}
void Operation1( )
{
pstate->Operation1();
pstate = pstate->pNext;
}
void Operation2( )
{
pstate->Operation2();
pstate = pstate->pNext;
}
void Operation3( )
{
pstate->Operation3();
pstate = pstate->pNext;
}
};
三、类图
总结
State模式将所有与一个特定状态相关的行为都放入一个state子类对象中,再对象切换的过程时,切换相应的对象;但同时维持State的接口,这样实现了具体操作和状态转换之间的解耦;
如果State对象没有实例变量,那么各个上下文可以公用一个state对象来节省开销;