benxintuzi

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

模式动机(Memento Pattern)我们在编辑文档时,经常需要将刚删除的内容恢复过来,这时最常用的就是撤销命令(Ctrl + Z)了,但是这种功能是如何实现的呢?

  可以猜想,其内部必然维护一个保存已删除内容的机制,这就是备忘录模式的用途了。

  其实在软件开发过程中,为了不同模块之间的交互,很多情况下需要记录一个对象内部状态的信息,以便可以进行恢复操作。比如,数据库的“回滚”操作,浏览器的“恢复上  一次”操作等。

备忘录模式的一般定义为:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样在某个时刻就可以将该对象恢复到原来的状态。

 

模式结构图:

 

模式代码:

bt_备忘录模式.h:

 1 #ifndef MP_H
 2 #define MP_H
 3 #include <iostream>
 4 using namespace std;
 5 
 6 /*
 7     状态结构体
 8 */
 9 typedef struct State
10 {
11 public:
12     State(int h = 0, int w = 0) : height(h), width(w){ };
13     void SetState(int h, int w)
14     {
15         height = h;
16         width = w;
17     }
18 
19     int height;
20     int width;
21 }State;
22 
23 /*
24     备忘录
25 */
26 class Memento
27 {
28 public:
29    Memento(State* s)
30    {
31         state = new State(s->height, s->width);     // new出新状态执行深复制
32   }
33   ~Memento()
34   {
35       delete state;
36   }
37     State* GetState() const
38     {
39         return state;
40     }
41     void SetState(State* state)
42     {
43         this->state = state;
44     }
45 private:
46     friend class Originator;
47     State* state;
48 
49 };
50 
51 /*
52     原发器
53 */
54 class Originator
55 {
56 public:
57     Originator(State* s) : state(s){ }
58     void SetMemento(const Memento* m)
59     {
60         this->state= m->GetState();
61     }
62     Memento* CreateMemento()
63     {
64         return new Memento(state);  // 此处若以指针类型的state传入构建新的备忘录,必须执行深复制,
65                                     // 否则后期改变state时,备忘录中的state状态将会跟着改变;
66                                     // 此外就是将state改为值传递形式,这样备忘录中保存的副本不受影响
67     }
68     // 显示当前状态
69     void Show()
70     {
71         cout << "当前状态为:";
72         cout << "height = " << state->height << ", " << "width = " << state->width << endl;
73     }
74 
75 private:
76     State* state;
77 };
78 
79 /*
80     管理者:负责保存、传递当前备忘录
81 */
82 class Caretaker
83 {
84 public:
85     void SetMemento(Memento* m)
86     {
87         this->memento= m;
88     }
89     Memento* GetMemento()
90     {
91         return memento;
92     }
93 private:
94     Memento* memento;
95 };
96 
97 #endif // MP_H

 

 

测试用例.cpp:

 1 #include "bt_备忘录模式.h"
 2 
 3 int main()
 4 {
 5     cout << "***** 备忘录模式测试 *****" << endl;
 6     State* s = new State(100, 50);
 7     Originator* original = new Originator(s);
 8     Caretaker* ct = new Caretaker();
 9     ct->SetMemento(original->CreateMemento());  // 用备忘录保存当前状态
10     original->Show();
11 
12     cout << endl;
13     s->SetState(200, 100);                      // 改变状态
14     original->Show();
15 
16     cout << endl;
17     original->SetMemento(ct->GetMemento());     // 恢复状态
18     original->Show();
19 
20     delete ct;
21     delete original;
22     delete s;
23 
24     return 0;
25 }

 

模式分析:

:: 备忘录用来存储原发器在前一时刻的内部状态,当需要设置恢复点时,管理者请求原发器创建一个备忘录,并记录原发器的当前状态。

:: 备忘录的状态只有创建它的原发器可以修改,因此将原发器类设为备忘录的友元类,用于访问备忘录的私有数据。

:: 管理者的作用是保存备忘录,必要时向原发器传递备忘录以恢复原发器的前一个状态。

:: 备忘录模式实现了状态恢复功能,其将原发器的内部状态进行保存,而且只允许创建它的原发器进行修改,封装性较好,同时若在管理者中采用栈来保存多个备忘录就可以实现   多次撤销操作。

:: 该模式与命令模式结合起来可以有效地实现撤销和重做命令,管理者可以利用STL容器来保存多个备忘录。

 

 

 

 

posted on 2015-06-10 16:19  benxintuzi  阅读(284)  评论(0编辑  收藏  举报