设计模式7:“状态变化模式”——State状态模式,Memento备忘录
在组建构建过程中,某些对象的状态经常面临变化,如何对这些变化进行有效的管理?同时又维持高层模块的稳定?“状态变化”模式为这一个问题提供了一种解决方案。
典型模式
- State
- Memento
State状态模式
动机(Motivation)
- 在软件构建过程中,某些对象的状态如果改变,其行为也会随之而发生变化,比如文档处于只读状态,其支持的行为和读写状态支持的行为就可能会完全不同。
- 如何在运行时根据对象的状态来透明地更改对象的行为?而不会为对象操作和状态转化之间引入紧耦合?
示例代码1:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 enum NetworkState 2 { 3 Network_Open, 4 Network_Close, 5 Network_Connect, 6 }; 7 8 class NetworkProcessor{ 9 10 NetworkState state; 11 12 public: 13 14 void Operation1(){ 15 if (state == Network_Open){ 16 17 //********** 18 state = Network_Close; 19 } 20 else if (state == Network_Close){ 21 22 //.......... 23 state = Network_Connect; 24 } 25 else if (state == Network_Connect){ 26 27 //$$$$$$$$$$ 28 state = Network_Open; 29 } 30 } 31 32 public void Operation2(){ 33 34 if (state == Network_Open){ 35 36 //********** 37 state = Network_Connect; 38 } 39 else if (state == Network_Close){ 40 41 //..... 42 state = Network_Open; 43 } 44 else if (state == Network_Connect){ 45 46 //$$$$$$$$$$ 47 state = Network_Close; 48 } 49 50 } 51 52 public void Operation3(){ 53 54 } 55 };
改进代码2:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 class NetworkState{ 2 3 public: 4 NetworkState* pNext; 5 virtual void Operation1()=0; 6 virtual void Operation2()=0; 7 virtual void Operation3()=0; 8 9 virtual ~NetworkState(){} 10 }; 11 12 13 class OpenState :public NetworkState{ 14 15 static NetworkState* m_instance; 16 public: 17 static NetworkState* getInstance(){ 18 if (m_instance == nullptr) { 19 m_instance = new OpenState(); 20 } 21 return m_instance; 22 } 23 24 void Operation1(){ 25 26 //********** 27 pNext = CloseState::getInstance(); 28 } 29 30 void Operation2(){ 31 32 //.......... 33 pNext = ConnectState::getInstance(); 34 } 35 36 void Operation3(){ 37 38 //$$$$$$$$$$ 39 pNext = OpenState::getInstance(); 40 } 41 42 43 }; 44 45 class CloseState:public NetworkState{ } 46 //... 47 48 49 class NetworkProcessor{ 50 51 NetworkState* pState; 52 53 public: 54 55 NetworkProcessor(NetworkState* pState){ 56 57 this->pState = pState; 58 } 59 60 void Operation1(){ 61 //... 62 pState->Operation1(); 63 pState = pState->pNext; 64 //... 65 } 66 67 void Operation2(){ 68 //... 69 pState->Operation2(); 70 pState = pState->pNext; 71 //... 72 } 73 74 void Operation3(){ 75 //... 76 pState->Operation3(); 77 pState = pState->pNext; 78 //... 79 } 80 81 };
模式定义
允许一个对象在其内部状态改变时改变它的行为。从而使对象看起来似乎修改了其行为。
——《设计模式》GoF
结构:
要点总结
- State模式将所有与一个特定状态相关的行为都放入一个State的子类对象中,在对象状态切换时, 切换相应的对象;但同时维持State的接口,这样实现了具体操作与状态转换之间的解耦。
- 为不同的状态引入不同的对象使得状态转换变得更加明确,而且可以保证不会出现状态不一致的情况,因为转换是原子性的——即要么彻底转换过来,要么不转换。
- 如果State对象没有实例变量,那么各个上下文可以共享同一个State对象,从而节省对象开销。
Memento备忘录
动机(Motivation)
- 在软件构建过程中,某些对象的状态在转换过程中,可能由于某种需求,要求程序能够回溯到对象之前处于某个点时的状态。如果使用一些公有接口来让其它对象得到对象的状态,便会暴露对象的实现细节。
- 如何实现对象状态的良好保存与恢复?但同时又不会因此而破坏对象本身的封装性。
示例代码
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 class Memento 2 { 3 string state; 4 //.. 5 public: 6 Memento(const string & s) : state(s) {} 7 string getState() const { return state; } 8 void setState(const string & s) { state = s; } 9 }; 10 11 class Originator 12 { 13 string state; 14 //.... 15 public: 16 Originator() {} 17 Memento createMomento() { 18 Memento m(state); 19 return m; 20 } 21 void setMomento(const Memento & m) { 22 state = m.getState(); 23 } 24 }; 25 26 27 int main() 28 { 29 Originator orginator; 30 31 //捕获对象状态,存储到备忘录 32 Memento mem = orginator.createMomento(); 33 34 //... 改变orginator状态 35 36 //从备忘录中恢复 37 orginator.setMomento(memento); 38 39 }
模式定义
在不破坏封装性的前提下,不活一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可以将该对象恢复到原想保存的状态。
——《设计模式》GoF
结构
要点总结
- 备忘录(Memento)存储原发器(Originator)对象的内部状态,在需要时恢复原发器的状态。
- Memento模式的核心是信息隐藏,即Originator需要向外接隐藏信息,保持其封装性。但同时又需要将其状态保持到外界(Memento)
- 由于现代语言运行时(如C#、java等)都具有相当的对象序列化支持,因此往往采用效率较高、又较容易正确实现的序列化方案来实现Memento模式。
小结
State
意图 | 允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类。 |
适用性 |
|
Memento
意图 | 在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态。 |
适用性 |
|
本文内容源自 :
- C++设计模式 Design Patterns 李建忠 课程;
- 设计模式:可复用面向对象软件的基础;