设计模式16-Memento

本文最后更新于:3 years ago

备忘录模式

  备忘录模式(Memento Pattern)保存一个对象的某个状态,以便在适当的时候恢复对象。备忘录模式属于 行为型模式

如果想了解备忘录模式的具体的介绍,菜鸟教程介绍得比较详细↓
菜鸟教程-备忘录模式

结构图


优缺点

优点:

1、给用户提供了一种可以恢复状态的机制,可以使用户能够比较方便地回到某个历史的状态。
2、实现了信息的封装,使得用户不需要关心状态的保存细节。

缺点:

消耗资源。如果类的成员变量过多,势必会占用比较大的资源,而且每一次保存都会消耗一定的内存。

使用场景

1、需要保存/恢复数据的相关状态场景。
2、提供一个可回滚的操作。

实现代码

这个模式比较好理解,就比如说我们在玩游戏的时候,你存了档,然后进行回档的话,其实就是备忘录模式
Windows中我们常用的Ctrl+z也就是这个模式。

Memento模式中Originator是发起人,负责创建一个备忘录Memento,用以记录当前时刻它的内部状态,并可使用备忘录恢复内部状态;Memento是备忘录,负责存储Originator对象的内部状态,并可防止Originator以外的其他对象访问备忘录MementoCaretaker是管理者,负责保存好备忘录的Memento,不能对备忘录的内容进行操作或检查。

模拟一个小游戏,我们让一个兔子进行随机的运动,每当一个时刻,我们就记录它的位置,
代码如下:

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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
public class Main {

public static void main(String[] args) {
Originator originator = new Originator();
CareTaker careTaker = new CareTaker();
Rabbit rabbit = new Rabbit(10, 20);
for (int i = 0; i < 10; i++) {
switch ((int) (Math.random() * 10) % 4) {
case 0:
rabbit.x += 5;
break;
case 1:
rabbit.x -= 5;
break;
case 2:
rabbit.y += 5;
break;
case 3:
rabbit.y -= 5;
break;
default:
System.out.println("no");
break;
}

if (i % 3 == 0) {
originator.setState(rabbit.toString());
careTaker.add(originator.saveStateToMemento());
}
}
for (int j = 0; j < 3; j++) {
originator.getStateFromMemento(careTaker.get(j));
System.out.println(j + " --> " + originator.getState());
}
}

}

public class Rabbit {
int x;
int y;

public Rabbit(int x, int y) {
this.x = x;
this.y = y;
}

@Override
public String toString() {
return "Rabbit{" +
"x=" + x +
", y=" + y +
'}';
}
}

public class Memento {
private String state;

public Memento(String state) {
this.state = state;
}

public String getState() {
return state;
}
}

public class Originator {
private String state;

public String getState() {
return state;
}

public void setState(String state) {
this.state = state;
}

public Memento saveStateToMemento(){
return new Memento(state);
}

public void getStateFromMemento(Memento Memento){
state = Memento.getState();
}
}

public class CareTaker {
private List<Memento> mementoList = new ArrayList<Memento>();

public void add(Memento state){
mementoList.add(state);
}

public Memento get(int index){
return mementoList.get(index);
}

public int getSize(){
return mementoList.size();
}
}

输出结果:

1
2
3
0 --> Rabbit{x=5, y=20}
1 --> Rabbit{x=5, y=25}
2 --> Rabbit{x=10, y=25}

输出结果就是记录着Rabbit的移动轨迹。

当我们在存档的时候,需要将当前的数据保存起来,保存的数据就存在Originator
如果我们想要读档的时候,那么将Originator中的数据读出即可,并且,读档的功能也是通过Originator实现的
但是我们存档当然不可能就是存一个,多个存档就需要存储在CareTaker

这就是备忘录的基本思想,这个模式在开发的时候还是用得比较多的模式,需要好好理解一下


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!