leisurexi's Blog.

备忘录模式

字数统计: 1.3k阅读时长: 5 min
2019/05/16 Share

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

模式定义

 所谓备忘录模式就是在不破坏封装的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样可以在以后将这个对象恢复到原先保存的状态。

模式结构

结构图

备忘录模式主要包含以下几个角色:

Originator(发起人):负责创建一个备忘录Memento,用以记录当前时刻它的内部状态,并可使用备忘录恢复状态。Originator可根据需求决定Memento存储Originator的哪些内部状态。

Memento(备忘录):负责存储Originator对象的内部状态,并可防止Originator以外的其他对象访问备忘录Memento。备忘录有两个接口,Caretaker只能看到备忘录的窄接口,它只能将备忘录传递给其他对象。Originator能够看到一个宽接口,允许它访问返回到先前状态所需的所有数据。

Caretaker(管理者):负责保存好备忘录Memento,不能对备忘录的内容进行操作或检查。

备忘录基本代码

 发起人(Originator)类

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
public class Originator {

//需要保存的属性
private String state;

//创建备忘录,将当前需要保存的信息导入并实例化出一个Memento对象
public Memento createMemento() {
return new Memento(state);
}

//恢复备忘录,将Memento导入并将相关数据恢复
public void setMemento(Memento memento) {
this.state = memento.getState();
}

//显示数据
public void show() {
System.out.println("state = " + state);
}

public String getState() {
return state;
}

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

 备忘录(Memento)类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class Memento {

private String state;

//构造方法,将相关数据导入
public Memento(String state) {
this.state = state;
}

public String getState() {
return state;
}

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

 管理者(Caretaker)类

1
2
3
4
5
6
7
8
9
10
11
12
public class Caretaker {

private Memento memento;

public Memento getMemento() {
return memento;
}

public void setMemento(Memento memento) {
this.memento = memento;
}
}

 客户端程序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class Client {

public static void main(String[] args) {
Originator originator = new Originator();
originator.setState("On");
originator.show();

Caretaker caretaker = new Caretaker();
caretaker.setMemento(originator.createMemento());

originator.setState("Off");
originator.show();

originator.setMemento(caretaker.getMemento());
originator.show();

}

}

 运行结果

1
2
3
state = On
state = Off
state = On

模式实现

 实现场景:游戏中的某个场景,一游戏角色有生命力、攻击力、防御力等数据,在打Boss前和后一定会不一样的,我们允许玩家如果感觉与Boss决斗的效果不理想可以让游戏恢复到决斗之前。

 代码结构图

结构图

 游戏角色类

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
public class GameRole {

private int vit; //生命力
private int atk; //攻击力
private int def; //防御力

//初始化状态
public void initState() {
this.vit = 100;
this.atk = 100;
this.def = 100;
}

//战斗
public void fight() {
this.vit = 0;
this.atk = 0;
this.def = 0;
}

//保存角色状态
public RoleStateMemento saveState() {
return new RoleStateMemento(vit, atk, def);
}

//回复角色状态
public void recoverState(RoleStateMemento roleStateMemento) {
this.vit = roleStateMemento.getVit();
this.atk = roleStateMemento.getAtk();
this.def = roleStateMemento.getDef();
}

public void stateDisplay() {
System.out.println("角色生命力:" + vit);
System.out.println("角色攻击力:" + atk);
System.out.println("角色防御力:" + def);

}

public int getVit() {
return vit;
}

public void setVit(int vit) {
this.vit = vit;
}

public int getAtk() {
return atk;
}

public void setAtk(int atk) {
this.atk = atk;
}

public int getDef() {
return def;
}

public void setDef(int def) {
this.def = def;
}
}

 游戏状态存储类

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
public class RoleStateMemento {

private int vit;
private int atk;
private int def;

public RoleStateMemento(int vit, int atk, int def) {
this.vit = vit;
this.atk = atk;
this.def = def;
}

public int getVit() {
return vit;
}

public void setVit(int vit) {
this.vit = vit;
}

public int getAtk() {
return atk;
}

public void setAtk(int atk) {
this.atk = atk;
}

public int getDef() {
return def;
}

public void setDef(int def) {
this.def = def;
}
}

 角色状态管理者类

1
2
3
4
5
6
7
8
9
10
11
12
public class RoleStateCaretaker {

private RoleStateMemento roleStateMemento;

public RoleStateMemento getRoleStateMemento() {
return roleStateMemento;
}

public void setRoleStateMemento(RoleStateMemento roleStateMemento) {
this.roleStateMemento = roleStateMemento;
}
}

 客户端程序

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
public class Client {

public static void main(String[] args) {

System.out.println("------------大战Boss前------------");
//大战Boss前
GameRole gameRole = new GameRole();
gameRole.initState();
gameRole.stateDisplay();

//保存进度
RoleStateCaretaker roleStateCaretaker = new RoleStateCaretaker();
roleStateCaretaker.setRoleStateMemento(gameRole.saveState());
System.out.println("------------大战Boss后------------");
//大战Boss时,损耗严重
gameRole.fight();
gameRole.stateDisplay();
System.out.println("------------恢复之前状态------------");
//恢复之前状态
gameRole.recoverState(roleStateCaretaker.getRoleStateMemento());
gameRole.stateDisplay();

}

}

 运行结果

1
2
3
4
5
6
7
8
9
10
11
12
------------大战Boss前------------
角色生命力:100
角色攻击力:100
角色防御力:100
------------大战Boss后------------
角色生命力:0
角色攻击力:0
角色防御力:0
------------恢复之前状态------------
角色生命力:100
角色攻击力:100
角色防御力:100

模式的优缺点

优点

  • 实现了信息的封装,使得用户不需要关心状态的保存细节。

  • 给用户提供了一种可以恢复状态的机制,可以使用户能够比较方便地回到某个历史的状态。

缺点

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

模式适用场景

 很多时候我们总是需要记录一个对象的内部状态,这样做的目的是为了允许用户取消不确定或者错误的操作,能够恢复到他原先的状态,使得他有”后悔药”可吃。

CATALOG
  1. 1. 模式定义
  2. 2. 模式结构
  3. 3. 模式实现
  4. 4. 模式的优缺点
  5. 5. 模式适用场景