网站建设五行,软件工程主要课程,设计制作服务方案,静安正规的设计公司网站State和Memento被归为“状态变化”模式。 文章目录 1. “状态变化”模式1.1 典型模式 2. 动机 (Motivation)3. 代码演示State 状态模式3.1 常规方式3.2 State 状态模式 4. 模式定义5. 结构( Structure )6. 要点总结7. 其他参考 1. “状态变化”模式
在组件构建过程中#xf…State和Memento被归为“状态变化”模式。 文章目录 1. “状态变化”模式1.1 典型模式 2. 动机 (Motivation)3. 代码演示State 状态模式3.1 常规方式3.2 State 状态模式 4. 模式定义5. 结构( Structure )6. 要点总结7. 其他参考 1. “状态变化”模式
在组件构建过程中某些对象的状态经常面临变化如何对这些变化进行有效的管理?同时又维持高层模块的稳定?“状态变化”模式为这一问题提供了一种解决方案。
1.1 典型模式
StateMemento
2. 动机 (Motivation)
在软件构建过程中某些对象的状态如果改变其行为也会随之而发生变化比如文档处于只读状态其支持的行为和读写状态支持的行为就可能完全不同。如何在运行时根据对象的状态来透明地更改对象的行为?而不会为对象操作和状态转化之间引入紧耦合?
3. 代码演示State 状态模式
3.1 常规方式
假设有一个网络的应用会根据网路状态做一些调整比如网络有打开关闭连接三种状态
enum NetworkState
{Network_Open,Network_Close,Network_Connect,
};下面的类为网络的应用NetworkState state;是网络的状态Operation1()在打开状态Network_Open下具有不同的行为执行完后最后状态变为close…Operation2()则是另外的行为在打开状态Network_Open下具有不同的行为执行完后最后状态变为Network_Connect…。
整体代码如下
class NetworkProcessor{NetworkState state;public:void Operation1(){if (state Network_Open){//**********state Network_Close;}else if (state Network_Close){//..........state Network_Connect;}else if (state Network_Connect){//$$$$$$$$$$state Network_Open;}}public void Operation2(){if (state Network_Open){//**********state Network_Connect;}else if (state Network_Close){//.....state Network_Open;}else if (state Network_Connect){//$$$$$$$$$$state Network_Close;}}public void Operation3(){}
};动机 (Motivation)中提到的“对象的状态如果改变其行为也会随之而发生变化”Operation1()中的if…else已经很清楚的表明了Operation1根据状态不同而行为不同。
上面的写法会有什么问题看到这段代码大家可能会有似曾相识的感觉根据上面代码来看和Strategy模式时碰到的问题是一样的代码中出现了很多的if…else而且if…else是有关业务状态。Strategy模式告诉我们对于这种情况我们应该问一个为什么
以下的枚举类型以后会不会有其他的类型出现如果添加了一种新的状态假设增加了Network_Wait之前的代码如何更改
enum NetworkState
{Network_Open,Network_Close,Network_Connect,Network_Wait
};增加了新的状态之后在不同的operation中需要增加新的if…else。这样的做法显然是违背了开闭原则。即需求的变更导致需要在代码中不断地去改这些地方。
3.2 State 状态模式
上面的做法肯定是不好的好的做法是参考Strategy模式的经验先提抽象基类把枚举类型转换为一个抽象基类
class NetworkState{public:NetworkState* pNext;virtual void Operation1()0;virtual void Operation2()0;virtual void Operation3()0;virtual ~NetworkState(){}
};所有跟状态有关的操作Operation1()等全部变为状态对象的行为并利用多态的虚函数来进行表达并塞入一个NetworkState* pNext;状态对象的指针。
创建OpenState其中使用了前面所讲的单例模式在状态中倾向使用单例模式因为状态的对象没必要有多个。此处Operation1()里面省略部分的内容是与上面常规的方式是有差别的核心逻辑肯定是类似的经过Operation1()之后就变为close状态此时pNext CloseState::getInstance()换的是一个对象而不是一个枚举。总之是将状态相关的操作全部编码到一个状态对象中。
如果是在open状态而且执行的是Operation1()的时候会执行怎样的行为执行完之后下一个状态会切换为哪个状态。
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 OpenState::getInstance();}};以此类推得到了close状态等需要做状态对象。
整个网络应用就改写为状态对象而不是枚举字段这种方式与strategy处理的手法是异曲同工。Operation1()中先做收集参数工作调用pState-Operation1();(虚函数的本质是运行时的if…else在运行时会判断pState的指针如果指向的是open状态就会调用open状态的operation1如果指向的是不同状态就会执行对应状态的operation1)执行完之后就让其等于下一个状态 pState pState-pNext;下一个状态是Operation1()内部pNext ConnectState::getInstance();更改的状态我本身不用管。
class NetworkProcessor{NetworkState* pState;public://构造器中初始化pStateNetworkProcessor(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;//...}};上面这样做的好处是与Strategy异曲同工。当状态增加的时候假如增加一个WaitState仍然是像上面操作写WaitState里的operation而NetworkProcessor里是不用改变的NetworkProcessor不关心其是什么状态只关心状态上的行为是对的状态行为里去自己去管理状态转换关系是一种扩展的方法。
下为整体代码
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 OpenState::getInstance();}};class CloseState:public NetworkState{ }
//...//扩展
class WaitState:public NetworkState{ }class NetworkProcessor{NetworkState* pState;public:NetworkProcessor(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;//...}};4. 模式定义
允许一个对象在其内部状态改变时改变它的行为。从而使对象看起来似乎修改了其行为。
----《设计模式》GoF
5. 结构( Structure ) 上图是《设计模式》GoF中定义的State 状态模式的设计结构。结合上面的代码看图中最重要的是看其中稳定和变化部分也就是下图中红框和蓝框框选的部分。 State 状态模式和Strategy非常像State中放的是一个行为一般是多个行为一个行为时和Strategy没什么两样的。
6. 要点总结 State模式将所有与一个特定状态相关的行为都放入一个State的子类对象中在对象状态切换时切换相应的对象;但同时维持State的接口这样实现了具体操作与状态转换之间的解耦。 为不同的状态引入不同的对象使得状态转换变得更加明确而且可以保证不会出现状态不一致的情况因为转换是原子性的–即要么彻底转换过莱要么不转换
openstate值关心三个操作之后的下一个状态是什么不需要太多的想更多耦合的情况。相比最初代码实现解耦。
如果state对象没有实例变量那么各个上下文可以共享同一个State对象从而节省对象开销
State 状态模式讲下来和Strategy非常像当最后往回看的时候你会发现很多模式越来越像相同点越来越多学习模式最后会发现这些模式之间差别会很小会忘掉具体的模式名称。不一定非要纠结模式的名称只是松耦合设计原则的演化。你可以将State 状态模式和Strategy看做同一个模式出现的问题是If…else枚举怎么转利用多态方式实现运行时的改变。掌握了这些具体是什么模式就没那么重要了。
7. 其他参考
C设计模式——状态模式