编程中的‘后悔药’-备忘录模式
模式简介
再不破坏封闭的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样,以后就可以将该对象恢复到原先保存状态。
应用场景
- 需要保存一个对象在某一时刻的状态或者部分状态
- 如果用一个接口来让其他对象得到这些状态,将会暴露对象的实现细节并破坏对象的封装性,一个对象不希望外接直接访问其内部状态,通过中间对象可以间接访问其内部状态
简单实现
使命召唤游戏
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
|
package MementoPattern;
//使命召唤游戏
public class CallOfDuty {
private int mCheckpoint=1;
private int mLifeValue=100;
private String mWeapon="沙漠之鹰";
//玩游戏
public void play(){
System.out.println("玩游戏:"+String.format("第%d关",mCheckpoint)+"奋战杀敌中");
mLifeValue-=10;
System.out.println("进度升级了");
mCheckpoint++;
System.out.println("到达"+String.format("第%d关",mCheckpoint));
}
//退出游戏
public void quit(){
System.out.println("----------");
System.out.println("退出游戏前属性:"+this.toString());
System.out.println("退出游戏");
System.out.println("----------");
}
//创建备忘录
public Memoto createMemoto(){
Memoto memoto=new Memoto();
memoto.mCheckpoint=mCheckpoint;
memoto.mLifeValue=mLifeValue;
memoto.mWeapon=mWeapon;
return memoto;
}
//恢复游戏
public void restore(Memoto memoto){
this.mCheckpoint=memoto.mCheckpoint;
this.mLifeValue=memoto.mLifeValue;
this.mWeapon=memoto.mWeapon;
System.out.println("恢复游戏后的属性:"+this.toString());
}
public int getmCheckpoint() {
return mCheckpoint;
}
public void setmCheckpoint(int mCheckpoint) {
this.mCheckpoint = mCheckpoint;
}
public int getmLifeValue() {
return mLifeValue;
}
public void setmLifeValue(int mLifeValue) {
this.mLifeValue = mLifeValue;
}
public String getmWeapon() {
return mWeapon;
}
public void setmWeapon(String mWeapon) {
this.mWeapon = mWeapon;
}
@Override
public String toString() {
return "CallOfDuty{" +
"mCheckpoint=" + mCheckpoint +
", mLifeValue=" + mLifeValue +
", mWeapon='" + mWeapon + '\'' +
'}';
}
}
|
管理类:责管理备忘录
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
package MementoPattern;
//Caretaker 管理类,负责管理Memoto
public class Caretaker {
Memoto memoto;//备忘录
//存档
public void archive(Memoto memoto){
this.memoto=memoto;
}
//获取存档
public Memoto getMemoto(){
return memoto;
}
}
|
备忘录类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
package MementoPattern;
//备忘录类
public class Memoto {
public int mCheckpoint;
public int mLifeValue;
public String mWeapon;
@Override
public String toString() {
return "Memoto{" +
"mCheckpoint=" + mCheckpoint +
", mLifeValue=" + mLifeValue +
", mWeapon='" + mWeapon + '\'' +
'}';
}
}
|
测试代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
package MementoPattern;
public class Client {
public static void main(String[] args) {
//构建对象
CallOfDuty callOfDuty=new CallOfDuty();
//打游戏
callOfDuty.play();
Caretaker caretaker=new Caretaker();
//游戏存档
caretaker.archive(callOfDuty.createMemoto());
//退出游戏
callOfDuty.quit();
//恢复游戏
CallOfDuty game=new CallOfDuty();
game.restore(caretaker.getMemoto());
}
}
|
执行结果
总结
备忘录模式是在不破坏封装的条件下,通过备忘录对象(Memoto)存储另外一个对象内部状态的快照,在将来合适的时候把这个对象还原到存储起来的状态。
优点:
- 给用户提供了一种可以恢复状态的机制,可以使用户能够比较方便的回到某个历史状态。
- 实现了信息的封装,使得用户不需要关心状态的保存细节
缺点:
消耗资源,如果类的成员变量过多,势必会占用比较大的资源,而且每一次保存都会消耗一定的内存。