行为型 - 备忘录(Memento)

备忘录模式(Memento pattern): 要在不破坏封装行的前提下,捕获并保存一个类的内部状态,这样就可以利用该保存的状态实施恢复操作。

概念

Memento 模式典型的结构图为:

代码实现

#ifndef _MEMENTO_H_
#define _MEMENTO_H_
#include <string>
using namespace std;
class Memento;
class Originator
{
public:
    typedef string State;
    Originator();
    Originator(const State &sdt);
    ~Originator();
    Memento *CreateMemento();
    void SetMemento(Memento *men);
    void RestoreToMemento(Memento *mt);
    State GetState();
    void SetState(const State &sdt);
    void PrintState();

protected:
private:
    State _sdt;
    Memento *_mt;
};

class Memento
{
public:
protected:
private:
    //这是最关键的地方,将 Originator 为friend 类,可以访问内部信息,但是其他类不能访问
    friend class Originator;
    typedef string State;
    Memento();
    Memento(const State &sdt);
    ~Memento();
    void SetState(const State &sdt);
    State GetState();

private:
    State _sdt;
};
#endif //~_MEMENTO_H_
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#include "Memento.h"
#include <iostream>
using namespace std;
typedef string State;

Originator::Originator()
{
    _sdt = "";
    _mt = 0;
}
Originator::Originator(const State &sdt)
{
    _sdt = sdt;
    _mt = 0;
}

Originator::~Originator()
{
}

Memento *Originator::CreateMemento()
{
    return new Memento(_sdt);
}

State Originator::GetState()
{
    return _sdt;
}

void Originator::SetState(const State &sdt)
{
    _sdt = sdt;
}

void Originator::PrintState()
{
    cout << this->_sdt << "....." << endl;
}

void Originator::SetMemento(Memento *men)
{
}

void Originator::RestoreToMemento(Memento *mt)
{
    this->_sdt = mt->GetState();
}

// class Memento
Memento::Memento()
{
}

Memento::Memento(const State &sdt)
{
    _sdt = sdt;
}

State Memento::GetState()
{
    return _sdt;
}

void Memento::SetState(const State &sdt)
{
    _sdt = sdt;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
#include "Memento.h"
#include <iostream>
using namespace std;
int main(int argc, char *argv[])
{
    Originator *o = new Originator();
    o->SetState("old"); //备忘前状态
    o->PrintState();

    Memento *m = o->CreateMemento(); //将状态备忘
    o->SetState("new"); //修改状态
    o->PrintState();
    
    o->RestoreToMemento(m); //恢复修改前状态
    o->PrintState();
    return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[root@VM-16-6-centos Memento]# ./MementoTest
old.....
new.....
old.....
1
2
3
4

代码说明

Memento 模式的关键就是 friend class Originator;可以看到 Memento 的接口都声明为 private,而将 Originator 声明为 Memento 的友元类。我们将 Originator 的状态保存在 Memento 类中,而将 Memento 接口 private 起来, 也就达到了封装的功效。在 Originator 类中我们提供了方法让用户后悔: RestoreToMemento(Memento* mt);我们可以通过这个接口让用户后悔。在测试程序中,我们演示了这一点: Originator 的状态由 old 变为 new 最后又回到了 old。

讨论

在 Command 模式中, Memento 模式经常被用来维护可以撤销( Undo) 操作的状态。 这一点将在 Command 模式具体说明。