备忘录模式(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;
public Memento createMemento() { return new Memento(state); }
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前------------"); GameRole gameRole = new GameRole(); gameRole.initState(); gameRole.stateDisplay();
RoleStateCaretaker roleStateCaretaker = new RoleStateCaretaker(); roleStateCaretaker.setRoleStateMemento(gameRole.saveState()); System.out.println("------------大战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
|
模式的优缺点
优点
缺点
- 如果类的成员变量过多,势必会占用比较大的资源,而且每一次保存都会消耗一定的内存。
模式适用场景
很多时候我们总是需要记录一个对象的内部状态,这样做的目的是为了允许用户取消不确定或者错误的操作,能够恢复到他原先的状态,使得他有”后悔药”可吃。