备忘录模式(Memento Pattern):又叫快照模式或Token模式,通俗的说,备忘录模式就是将一个对象进行备份,提供一种程序数据的备份方法;
在不破坏封装的前提下,捕获一个对象的内部状态,并在对象之外保存这个状态,这样,以后就可以将该对象恢复到原先保存的状态
备忘录模式的三个角色:
- 发起人(Originator)角色:该角色记录当前时刻的内部状态,负责定义哪些属于备份范围的状态,负责创建和恢复备份数据
- 备忘录(Memento)角色:该角色负责存储发起人角色的内部状态
- 负责人(Caretaker)角色:该角色负责对备忘录角色进行管理,向发起人角色保存和提供备忘录
备忘录模式比较适用于功能比较复杂的,但需要维护或记录属性历史的类,或者需要保存的属性只是众多属性中的一小部分时。
备忘录模式基础代码实现:
public class MementoModle {
/*
* 备忘录模式
*/
public static void main(String[] args) {
Originator originator = new Originator();//发起人
originator.setState("初始状态A");// 可以被备份的数据
originator.setOtherData("初始状态B");// 不会被备份的数据——一般为不变数据
System.out.println("1、\n" + originator);
Carataker carataker = new Carataker();// 创建管理者
carataker.setMemento(originator.backup());// 添加备份
originator.setState("状态A改变");// 修改数据
System.out.println("2、\n" + originator);
originator.restor(carataker.getMemento());// 恢复备份
System.out.println("3、\n" + originator);
}
}
//发起人
class Originator {
private String state;// 需要备份的状态
private String otherData;// 不需要备份的数据
// get/set方法
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public String getOtherData() {
return otherData;
}
public void setOtherData(String otherData) {
this.otherData = otherData;
}
// 开始备份
public Memento backup() {
return new Memento(state);
}
// 恢复备份
public void restor(Memento memento) {
this.state = memento.restor();
}
public String toString() {
return "需要备份的数据:" + state + "\n无需备的数据:" + otherData;
}
}
//备忘录
class Memento {
private String state;// 备份的状态
public Memento(String state) {
this.state = state;
}
public String restor() {
return state;
}
}
//管理者——目的是对备份进行管理,一般以一个集合来管理多备份
class Carataker {
private Memento memento;
public Memento getMemento() {
return memento;
}
public void setMemento(Memento memento) {
this.memento = memento;
}
}
运行结果:
1、
需要备份的数据:初始状态A
无需备的数据:初始状态B
2、
需要备份的数据:状态A改变
无需备的数据:初始状态B
3、
需要备份的数据:初始状态A
无需备的数据:初始状态B
备忘录模式实例——游戏存档:
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class MementoModle {
/*
* 备忘录模式
*/
public static void main(String[] args) {
//备忘录模式实例测试——游戏存档
//创建游戏角色
Gamer gamer1=new Gamer("a123","科菲", "女", "法师");
Gamer gamer2=new Gamer("b234","策行", "男", "战士");
Manager bmanager=new Manager();//备份管理类
//添加备份1
gamer1.setProgress("关卡2");
gamer1.setTime("21:00");
gamer2.setProgress("关卡2");
gamer2.setTime("21:00");
bmanager.setBackUp(gamer1.addBackup());//为角色a123添加备份
bmanager.setBackUp(gamer2.addBackup());//为角色b234添加备份
//添加备份2
gamer1.setProgress("关卡3");
gamer1.setTime("22:00");
gamer2.setProgress("关卡3");
gamer2.setTime("22:00");
bmanager.setBackUp(gamer1.addBackup());//为角色a123添加备份
bmanager.setBackUp(gamer2.addBackup());//为角色b234添加备份
gamer1.setProgress("关卡4");
gamer1.setTime("23:00");
gamer2.setProgress("关卡4");
gamer2.setTime("23:00");
//游戏到第4关,玩家a123想重玩关卡2、玩家b234想重玩关卡3
//打印游戏当前进度
System.out.println(gamer1);
System.out.println(gamer2);
//恢复备份
gamer1.restore(bmanager.getBackUp("a123", "21:00"));//角色a123返回到关卡2
gamer2.restore(bmanager.getBackUp("b234", "22:00"));//角色b234返回到关卡3
System.out.println(gamer1);
System.out.println(gamer2);
}
}
//备忘录模式实例——游戏存档——根据角色Id和游戏时间备份游戏进度
class Gamer {
private String roleId;// 角色id
private String roleName;// 角色名字
private String roleSex;// 角色性别
private String roleType;// 角色类型
private String progress;// 游戏进度
private String time;//游戏时间
public String getTime() {
return time;
}
public void setTime(String time) {
this.time = time;
}
public String getProgress() {
return progress;
}
public void setProgress(String progress) {
this.progress = progress;
}
// get/set方法
public String getRoleId() {
return roleId;
}
public void setRoleId(String roleId) {
this.roleId = roleId;
}
public String getRoleName() {
return roleName;
}
public void setRoleName(String roleName) {
this.roleName = roleName;
}
public String getRoleSex() {
return roleSex;
}
public void setRoleSex(String roleSex) {
this.roleSex = roleSex;
}
public String getRoleType() {
return roleType;
}
public void setRoleType(String roleType) {
this.roleType = roleType;
}
public Gamer(String roleId,String roleName, String roleSex, String roleType) {
this.roleId=roleId;
this.roleName = roleName;
this.roleSex = roleSex;
this.roleType = roleType;
}
// 备份
public BackUp addBackup() {
return new BackUp(roleId, progress,time);
}
// 恢复备份
public void restore(BackUp backUp) {
this.progress = backUp.getProgress();
}
//打印角色信息
public String toString() {
return "角色ID:"+roleId+"\t游戏进度:"+progress;
}
}
//备份——根据角色Id和游戏时间备份游戏进度
class BackUp {
private String roleId;// 角色id
private String time;//备份时间
private String progress;// 游戏进度
public String getTime() {
return time;
}
public void setTime(String time) {
this.time = time;
}
public String getRoleId() {
return roleId;
}
public void setRoleId(String roleId) {
this.roleId = roleId;
}
public String getProgress() {
return progress;
}
public void setProgress(String progress) {
this.progress = progress;
}
public BackUp(String roleId, String progress,String time) {
this.roleId = roleId;
this.progress = progress;
this.time=time;
}
}
//备份管理——添加备份/读取备份
class Manager {
private Map<String, List<BackUp>> map = new HashMap<String, List<BackUp>>();
private List<BackUp> list;
public void setBackUp(BackUp backup) {
if (map.get(backup.getRoleId()) != null) {
list = map.get(backup.getRoleId());
list.add(backup);
map.put(backup.getRoleId(), list);
} else {
list = new ArrayList<BackUp>();
list.add(backup);
map.put(backup.getRoleId(), list);
}
}
public BackUp getBackUp(String roleId,String time) {
for(BackUp backup:map.get(roleId)) {
if(backup.getTime().equals(time)) {
return backup;
}
}return null;
}
}
运行结果:
角色ID:a123 游戏进度:关卡4
角色ID:b234 游戏进度:关卡4
角色ID:a123 游戏进度:关卡2
角色ID:b234 游戏进度:关卡3
参考资料:
《大话设计模式》——程杰
《设计模式(Java版)》