设计模式7:“状态变化模式”——State状态模式,Memento备忘录

      在组建构建过程中,某些对象的状态经常面临变化,如何对这些变化进行有效的管理?同时又维持高层模块的稳定?“状态变化”模式为这一个问题提供了一种解决方案。

典型模式

  • State
  • Memento

State状态模式

动机(Motivation)

  • 在软件构建过程中,某些对象的状态如果改变,其行为也会随之而发生变化,比如文档处于只读状态,其支持的行为和读写状态支持的行为就可能会完全不同。
  • 如何在运行时根据对象的状态来透明地更改对象的行为?而不会为对象操作和状态转化之间引入紧耦合?

示例代码1:

 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 };
state1

改进代码2:

 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 };
state2

模式定义

    允许一个对象在其内部状态改变时改变它的行为。从而使对象看起来似乎修改了其行为。                                 

                                                                                                    ——《设计模式》GoF

结构:

image

 要点总结

  • State模式将所有与一个特定状态相关的行为都放入一个State的子类对象中,在对象状态切换时, 切换相应的对象;但同时维持State的接口,这样实现了具体操作与状态转换之间的解耦。
  • 为不同的状态引入不同的对象使得状态转换变得更加明确,而且可以保证不会出现状态不一致的情况,因为转换是原子性的——即要么彻底转换过来,要么不转换。
  • 如果State对象没有实例变量,那么各个上下文可以共享同一个State对象,从而节省对象开销。

Memento备忘录

动机(Motivation)

  • 在软件构建过程中,某些对象的状态在转换过程中,可能由于某种需求,要求程序能够回溯到对象之前处于某个点时的状态。如果使用一些公有接口来让其它对象得到对象的状态,便会暴露对象的实现细节。
  • 如何实现对象状态的良好保存与恢复?但同时又不会因此而破坏对象本身的封装性。

示例代码

 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 }
Memento

模式定义

    在不破坏封装性的前提下,不活一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可以将该对象恢复到原想保存的状态。

                                                                                                             ——《设计模式》GoF

结构

image

要点总结

  • 备忘录(Memento)存储原发器(Originator)对象的内部状态,在需要时恢复原发器的状态。
  • Memento模式的核心是信息隐藏,即Originator需要向外接隐藏信息,保持其封装性。但同时又需要将其状态保持到外界(Memento)
  • 由于现代语言运行时(如C#、java等)都具有相当的对象序列化支持,因此往往采用效率较高、又较容易正确实现的序列化方案来实现Memento模式。

 


小结

State

意图 允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类。
适用性
  • 一个对象的行为取决于它的状态, 并且它必须在运行时刻根据状态改变它的行为。
  • 一个操作中含有庞大的多分支的条件语句,且这些分支依赖于该对象的状态。这个状态通常用一个或多个枚举常量表示。通常, 有多个操作包含这一相同的条件结构。State模式将每一个条件分支放入一个独立的类中。这使得你可以根据对象自身的情况将对象的状态作为一个对象,这一对象可以不依赖于其他对象而独立变化。  

Memento

意图 在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态。
适用性
  • 必须保存一个对象在某一个时刻的(部分)状态, 这样以后需要时它才能恢复到先前的状态。
  • 如果一个用接口来让其它对象直接得到这些状态,将会暴露对象的实现细节并破坏对象的封装性。 

本文内容源自 :

  1. C++设计模式 Design Patterns 李建忠 课程;
  2. 设计模式:可复用面向对象软件的基础;

posted on 2017-12-09 17:32  flysong  阅读(125)  评论(0编辑  收藏  举报

导航