Luckylau's Blog

设计模式之备忘录模式

​ 备忘录模式(Memento pattern)又叫快照模式(Snapshot pattern),是对象的行为模式。用于保存一个对象的某个状态,以便在适当的时候恢复对象。

​ 虚拟机估计大多数人都用过,虚拟机有一个很不错的功能就是“打快照”,把系统调到最舒服的状态,装好该装的软件,然后打个快照,就可以把当前的系统状态保存下来,一旦哪一天系统搞坏了,再用这个快照恢复一下就好了。虚拟机可以在开机和关机状态下打快照。关机状态下,保存虚拟磁盘的状态就好了,就像我们物理机把硬盘保存好,换到别的物理机上启动;开机状态下,除了虚拟磁盘的存储快照,还会将内存的状态保存为内存快照到物理存储上,恢复快照后的系统仍然是运行中的状态,内存快照会重新加载到内存中,因此所打开的应用会继续快照时候的状态执行,就像物理机的休眠。如果要模拟这个过程,就可以使用备忘录模式/快照模式(以下叫“快照模式”吧)。

1
2
public interface Snapshot {
}
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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
package com.getset.designpatterns.memento;
import java.util.ArrayList;
import java.util.List;
public class VirtualMachine {
// 虚拟机名称
private String name;
// 虚拟机配置
private String devices;
// 虚拟机内存内容,简化为一个String的列表
private List<String> memory;
// 虚拟机存储内容,简化为一个String的列表
private List<String> storage;
// 虚拟机状态
private String state;
public VirtualMachine(String name, String devices) {
this.name = name;
this.devices = devices;
this.memory = new ArrayList<String>();
this.storage = new ArrayList<String>();
this.state = "created";
}
/**
* 创建虚拟机
* @param name 虚拟机名称
* @param devices 虚拟机配置
*/
public VirtualMachine createVM(String name, String devices) {
return new VirtualMachine(name, devices);
}
// 开机
public void startup() {
this.state = "running";
System.out.println("虚拟机" + name + "已启动");
}
// 关机
public void halt() {
this.state = "shutdown";
System.out.println("虚拟机" + name + "已关机");
}
// 暂停
public void suspend() {
this.state = "suspending";
System.out.println("虚拟机" + name + "已暂停");
}
// 暂停后恢复
public void resume() {
this.state = "running";
System.out.println("虚拟机" + name + "已恢复");
}
/**
* 打开应用,加载到内存,用来模拟内存中的内容
*/
public void openApp(String appName) {
if ("running".equals(state)) {
this.memory.add(appName);
System.out.println("虚拟机" + name + "打开应用: " + appName);
}
}
/**
* 关闭应用,从内存中删除,用来模拟内存中的内容
*/
public void closeApp(String appName) {
if ("running".equals(state)) {
this.memory.remove(appName);
System.out.println("虚拟机" + name + "关闭应用: " + appName);
}
}
/**
* 保存文件,写入虚拟磁盘,用来模拟存储中的内容
*/
public void saveFile(String file) {
if ("running".equals(state)) {
this.storage.add(file);
System.out.println("虚拟机" + name + "中保存文件: " + file);
}
}
/**
* 删除文件,从虚拟磁盘中删除,用来模拟存储中的内容
*/
public void delFile(String file) {
if ("running".equals(state)) {
this.storage.remove(file);
System.out.println("虚拟机" + name + "中删除文件: " + file);
}
}
/**
* 打快照,如果是开机状态会保存内存快照和存储快照;如果是关机状态则仅保存存储快照即可。
*/
public Snapshot takeSnapshot() {
if ("shutdown".equals(state)) {
return new VMSnapshot(null, new ArrayList<String>(storage));
} else {
return new VMSnapshot(new ArrayList<String>(memory), new ArrayList<String>(storage));
}
}
/**
* 恢复快照
*/
public void restoreSnapshot(Snapshot snapshot) {
VMSnapshot tmp = (VMSnapshot)snapshot;
this.memory = new ArrayList<String>(tmp.memory);
this.storage = new ArrayList<String>(tmp.storage);
if (tmp.memory == null) {
this.state = "shutdown";
}
}
@Override
public String toString() {
StringBuffer stringBuffer = new StringBuffer();
stringBuffer.append("------\n[虚拟机“" + name + "”] 配置为“" + devices + "”," + "目前状态为:" + state + "。");
if ("running".equals(state)) {
stringBuffer.append("\n 目前运行中的应用有:" + memory.toString());
stringBuffer.append("\n 最近保存的文件有:" + storage.toString());
}
stringBuffer.append("\n------");
return stringBuffer.toString();
}
private static class VMSnapshot implements Snapshot {
private List<String> memory;
private List<String> storage;
public VMSnapshot(List<String> memory, List<String> storage) {
this.memory = memory;
this.storage = storage;
}
public List<String> getMemory() {
return memory;
}
public List<String> getStorage() {
return storage;
}
public void setMemory(List<String> memory) {
this.memory = memory;
}
public void setStorage(List<String> storage) {
this.storage = storage;
}
}
}
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
public class User {
public static void main(String[] args) {
Stack<Snapshot> snapshots = new Stack<Snapshot>();
VirtualMachine ubuntu = new VirtualMachine("ubuntu", "1个4核CPU,8G内存,80G硬盘");
ubuntu.startup();
ubuntu.openApp("网易云音乐");
ubuntu.openApp("谷歌浏览器");
ubuntu.saveFile("/tmp/test.txt");
System.out.println(ubuntu);
snapshots.push(ubuntu.takeSnapshot());
ubuntu.closeApp("网易云音乐");
ubuntu.openApp("IntelliJ IDEA");
ubuntu.delFile("/tmp/test.txt");
ubuntu.saveFile("/workspace/hello.java");
System.out.println(ubuntu);
ubuntu.restoreSnapshot(snapshots.peek());
System.out.println("恢复到最近的快照...");
System.out.println(ubuntu);
}
}
Luckylau wechat
如果对您有价值,看官可以打赏的!