1. 程式人生 > >C++設計模式-Memento備忘錄模式

C++設計模式-Memento備忘錄模式

Memento模式
作用:在不破壞封裝性的前提下,捕獲一個物件的內部狀態,並在該物件之外儲存這個狀態,這樣以後就可將該物件恢復到原先儲存的狀態。

UML圖



Originator:負責建立一個備忘錄Memento,用以記錄當前時刻它的內部狀態,並可使用備忘錄恢復內部狀態。Originator可根據需要決定Memento儲存Originator的哪些內部狀態。

Memento:負責儲存Originator物件的內部狀態,並可防止Originator以外的其他物件訪問備忘錄Memento。備忘錄有兩個介面,Caretaker只能看到備忘錄的窄介面,它只能將備忘錄傳遞給其他物件。Originator能夠看到一個寬介面,允許它訪問返回到先前狀態所需的所有資料。

Caretaker:負責儲存好備忘錄Memento,不能對備忘錄的內容進行操作或檢查。

Memento模式中封裝的是需要儲存的狀態,當需要恢復的時候才取出來進行恢復.原理很簡單,實現的時候需要注意一個地方:窄介面和寬介面.所謂的寬介面就是一般意義上的介面,把對外的介面作為public成員;而窄介面反之,把介面作為private成員,而把需要訪問這些介面函式的類作為這個類的友元類,也就是說介面只暴露給了對這些介面感興趣的類,而不是暴露在外部.下面的實現就是窄實現的方法來實現的.

Memento模式比較適用於功能比較複雜的,但需要維護或記錄歷史屬性的類,或者需要儲存的屬性只是眾多屬性中的一小部分時,Originator可以根據儲存的Memento資訊還原到前一狀態。

如果在某個系統中使用命令模式時,需要實現命令的撤銷功能,那麼命令模式可以使用備忘錄模式來儲存可撤銷操作的狀態。

程式碼如下

Memento.h

複製程式碼
 1 #ifndef _MEMENTO_H_
 2 #define _MEMENTO_H_
 3 #include <string>
 4 
 5 using namespace std;
 6 
 7 //負責儲存Originator物件的內部狀態,並可防止Originator以外的其他物件訪問備忘錄Memento。
 8 //備忘錄有兩個介面,Caretaker只能看到備忘錄的窄介面,它只能將備忘錄傳遞給其他物件。Originator能夠看到一個寬介面,允許它訪問返回到先前狀態所需的所有資料。
 9 class Memento
10 {
11 private
: 12 //將Originator為friend類,可以訪問內部資訊,但是其他類不能訪問 13 friend class Originator; 14 Memento(const string& state); 15 ~Memento(); 16 void SetState(const string& state); 17 string GetState(); 18 string _state; 19 }; 20 21 //負責建立一個備忘錄Memento,用以記錄當前時刻它的內部狀態,並可使用備忘錄恢復內部狀態 22 class Originator 23 { 24 public: 25 Originator(); 26 Originator(const string& state); 27 ~Originator(); 28 void RestoreToMemento(Memento* pMemento); 29 Memento* CreateMemento(); 30 void SetState(const string& state); 31 string GetState(); 32 void show(); 33 protected: 34 private: 35 string _state; 36 }; 37 38 //負責儲存好備忘錄Memento,不能對備忘錄的內容進行操作或檢查 39 class Caretaker 40 { 41 public: 42 Caretaker(); 43 ~Caretaker(); 44 void SetMemento(Memento*); 45 Memento* GetMemento(); 46 private: 47 Memento* _memento; 48 }; 49 50 #endif
複製程式碼

Memento.cpp

複製程式碼
 1 #include "Memento.h"
 2 #include <iostream>
 3 #include <string>
 4 
 5 using namespace std;
 6 
 7 Memento::Memento(const string& state)
 8 {
 9     this->_state = state;
10 }
11 
12 Memento::~Memento()
13 {}
14 
15 string Memento::GetState()
16 {
17     return this->_state;
18 }
19 
20 void Memento::SetState(const string& state)
21 {
22     this->_state = state;
23 }
24 
25 Originator::Originator()
26 {}
27 
28 Originator::Originator(const string& state)
29 {
30     this->_state = state;
31 }
32 
33 Originator::~Originator()
34 {}
35 
36 string Originator::GetState()
37 {
38     return this->_state;
39 }
40 
41 void Originator::show()
42 {
43     cout << this->_state << endl;
44 }
45 
46 void Originator::SetState(const string& state)
47 {
48     this->_state = state;
49 }
50 
51 Memento* Originator::CreateMemento()
52 {
53     return new Memento(this->_state);
54 }
55 
56 void Originator::RestoreToMemento(Memento* pMemento)
57 {
58     this->_state = pMemento->GetState();
59 }
60 
61 Caretaker::Caretaker()
62 {}
63 
64 Caretaker::~Caretaker()
65 {}
66 
67 Memento* Caretaker::GetMemento()
68 {
69     return this->_memento;
70 }
71 
72 void Caretaker::SetMemento(Memento* pMemento)
73 {
74     this->_memento = pMemento;
75 }
複製程式碼

main.cpp

複製程式碼
 1 #include "Memento.h"
 2 
 3 int main()
 4 {
 5     //初始化物件,狀態為“Old”
 6     Originator* o = new Originator("Old");
 7     o->show();
 8 
 9     //建立並儲存Memento
10     Caretaker* pTaker = new Caretaker();
11     pTaker->SetMemento(o->CreateMemento());
12 
13     //改變狀態
14     o->SetState("New");
15     o->show();
16 
17     //恢復狀態
18     o->RestoreToMemento(pTaker->GetMemento());
19     o->show();
20 
21     return 0;
22 }
複製程式碼

結果如下: