备忘录模式
# 一、概述
备忘录(Memento)模式在不破坏对象的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。
# 1.1 解决了什么问题
不知道你有没有用过 Idea 的 Local History 功能,其实很多编辑器都提供快照恢复功能,当你在某一时刻对文件进行修改之后,它会在本地将当前时刻文件的状态(快照)记录下来。后续如果编辑出错或者因为其它原因,当你需要的时候就可以恢复到过去任意时刻的状态(快照)。备忘录模式就是解决这个问题的,它可以在对象之外保存该对象的状态。
# 1.2 解决方案
备忘录模式将对象状态的副本存储在一个名为备忘录(Memento)的特殊对象中,除了创建备忘录的对象外,任何对象都不能访问备忘录的内容。
# 二、实现方式
# 2.1 角色
- Originator:原发器,需要存储的就是这个角色的状态。它可以生成自身状态的快照,也可以在需要时通过快照恢复自身的状态。
- Memento:备忘录,原发器的快照对象,也就是说原发器的状态数据会存储在这个类中,通常会通过构造函数一次性传递数据。而且这个类一般是一个 POJO 类,需要保存原发器中的哪些属性的状态,这个类中就有哪些属性。
- Caretaker:负责人,负责生成以及记录多个快照。
# 2.2 代码
定义原发器对象:
public class Editor {
// 文本中的内容
private String text;
// 文本长度
private long length;
// 最后修改时间
private long timestamp;
public void edit(String text) {
this.text = text;
this.length = text.length();
this.timestamp = System.currentTimeMillis();
}
@Override
public String toString() {
return "Editor{" +
"text='" + text + '\'' +
", length=" + length +
", timestamp=" + timestamp +
'}';
}
/**
* 创建快照
*
* @return
*/
public EditorSnapshot createSnapshot() {
return new EditorSnapshot(text, length, timestamp);
}
/**
* 恢复快照
*
* @param snapshot
*/
public void restoreSnapshot(EditorSnapshot snapshot) {
this.text = snapshot.getText();
this.length = snapshot.getLength();
this.timestamp = snapshot.getTimestamp();
}
}
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
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
定义备忘录对象,因为需要保存的是Editor
的text
、length
和timestamp
三个属性,所以备忘录对象中也只有这三个字段。
public class EditorSnapshot {
private String text;
private long length;
private long timestamp;
public EditorSnapshot(String text, long length, long timestamp) {
this.text = text;
this.length = length;
this.timestamp = timestamp;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public long getLength() {
return length;
}
public void setLength(long length) {
this.length = length;
}
public long getTimestamp() {
return timestamp;
}
public void setTimestamp(long timestamp) {
this.timestamp = timestamp;
}
}
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
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
定义负责人,该对象用来管理多个快照,除了下面的增加快照和获取快照,还可以增加删除快照等。
public class Caretaker {
private List<EditorSnapshot> snapshots = new ArrayList<>();
/**
* 保存快照
*
* @param snapshot
*/
public void saveSnapshot(EditorSnapshot snapshot) {
this.snapshots.add(snapshot);
}
/**
* 获取快照
*
* @param index
* @return
*/
public EditorSnapshot getSnapshot(int index) {
return snapshots.get(index);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
示例:
public class MementoTest {
public static void main(String[] args) {
Caretaker caretaker = new Caretaker();
Editor editor = new Editor();
editor.edit("这是第一份快照");
caretaker.saveSnapshot(editor.createSnapshot());
editor.edit("这是第二份快照,多四个字");
caretaker.saveSnapshot(editor.createSnapshot());
editor.edit("This is the third snapshot");
caretaker.saveSnapshot(editor.createSnapshot());
System.out.println(editor);
// 恢复第一次的状态
editor.restoreSnapshot(caretaker.getSnapshot(0));
System.out.println(editor);
// 恢复第二次状态
editor.restoreSnapshot(caretaker.getSnapshot(1));
System.out.println(editor);
// 恢复第三次状态
editor.restoreSnapshot(caretaker.getSnapshot(2));
System.out.println(editor);
}
}
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
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
Editor{text='This is the third snapshot', length=26, timestamp=1663163957886}
Editor{text='这是第一份快照', length=7, timestamp=1663163957885}
Editor{text='这是第二份快照,多四个字', length=12, timestamp=1663163957886}
Editor{text='This is the third snapshot', length=26, timestamp=1663163957886}
1
2
3
4
2
3
4
# 三、源码中的应用
- java.io.Serializable
- javax.faces.component.StateHolder
上次更新: 2023/11/01, 03:11:44