备忘录模式(memento),是一种行为性模型,行为型模式关注的是系统中对象之间的相互交互,解决系统在运行时对象之间的相互通信和协作,进一步明确对象的职责。相比来说,创建型模式关注对象的创建过程,结构型模式关注对象和类的组合关系。
模式的职责
我们对一些操作,需要有保存状态,甚至需要恢复到之前状态的要求,这个时候可以使用备忘录模式。备忘录模式实际是要保存之前的状态,用来让机器可以恢复到之前的状态。
模式的结构
源发器类:被记录备忘的类
备忘录类:存储备忘信息的类
负责人类:保存和管理备忘录类的类(因为可能需要保存不止一个备忘信息)。
模式的实现
//需要存储的对象
public class PlayLoad {
//存储对象的属性
private String PlayLevel;
private int hp;
private int mp;
//存储对象的构造方法
public PlayLoad(String level,int hp,int mp){
this.PlayLevel = level;
this.hp = hp;
this.mp = mp;
}
//进行备忘信息,并返回备忘的备份
public Memento memento(){
return new Memento(this);
}
//取出备忘信息的方法
public void recovery(Memento memento){
this.PlayLevel = memento.getPlayLevel();
this.hp = memento.getHp();
this.mp = memento.getMp();
}
//相应属性的set和get方法
public String getPlayLevel() {
return PlayLevel;
}
public void setPlayLevel(String playLevel) {
PlayLevel = playLevel;
}
public int getHp() {
return hp;
}
public void setHp(int hp) {
this.hp = hp;
}
public int getMp() {
return mp;
}
public void setMp(int mp) {
this.mp = mp;
}
}
//备忘录类:保存备忘信息
public class Memento {
private String PlayLevel;
private int hp;
private int mp;
public Memento(PlayLoad load){
this.PlayLevel = load.getPlayLevel();
this.hp = load.getHp();
this.mp = load.getMp();
}
public String getPlayLevel() {
return PlayLevel;
}
public void setPlayLevel(String playLevel) {
PlayLevel = playLevel;
}
public int getHp() {
return hp;
}
public void setHp(int hp) {
this.hp = hp;
}
public int getMp() {
return mp;
}
public void setMp(int mp) {
this.mp = mp;
}
}
//负责人对象:负责存储备忘信息
public class CareTaker {
//由于备忘信息的特殊性,所以一般用栈来存储(其实这里更的情况更适合用List或者map存储,但是需要更多的判断)
private Stack<Memento>stack = new Stack<Memento>();
//取得最新存储信息
public Memento popM() {
return stack.pop();
}
//放入存储信息
public void pushtM(Memento m) {
this.stack.push(m);
}
}
//客户端调用
public class Client {
public static void main(String[] args) {
//新建负责人类对象
CareTaker c = new CareTaker();
//新建被备忘对象
PlayLoad p = new PlayLoad("第一关",2000,1900);
System.out.println("现在是"+p.getPlayLevel()+",还有血量"+p.getHp()+",还有魔法值"+p.getMp());
//第一次备忘
Memento m =p.memento();
//将备忘信息放入负责人对象中
c.pushtM(m);
p.setHp(1800);
p.setMp(1700);
p.setPlayLevel("第二关");
System.out.println("现在是"+p.getPlayLevel()+",还有血量"+p.getHp()+",还有魔法值"+p.getMp());
m = p.memento();
c.pushtM(m);
p.setHp(100);
p.setMp(100);
p.setPlayLevel("第三关");
System.out.println("现在是"+p.getPlayLevel()+",还有血量"+p.getHp()+",还有魔法值"+p.getMp());
p.recovery(c.popM());
System.out.println("现在是"+p.getPlayLevel()+",还有血量"+p.getHp()+",还有魔法值"+p.getMp());
p.recovery(c.popM());
System.out.println("现在是"+p.getPlayLevel()+",还有血量"+p.getHp()+",还有魔法值"+p.getMp());
}
}
输出的结果为:
现在是第一关,还有血量2000,还有魔法值1900
现在是第二关,还有血量1800,还有魔法值1700
现在是第三关,还有血量100,还有魔法值100
现在是第二关,还有血量1800,还有魔法值1700
现在是第一关,还有血量2000,还有魔法值1900
由此可见备忘信息已经可以成功的存储和取出。
模式的其他说明
其实本例子更应该用Map的方式去存储,因为游戏的存档读档对于顺序没有太高的要求,反而需要客户端能明白自己要调用的存储信息是哪个,用Map的键值对存储更适合。
但是对于像文档操作,软件操作的存档,比较适合用State去存储,因为一般恢复都是就近的操作存档进行恢复。