新的游戏功能
之前公司的游戏小明通过原型模式完成了游戏中的小怪对象,现在公司游戏有一个需求,需要定期保存游戏的进度,并且用户可以恢复到保存的进度
小明对于这个功能无从下手,于是请教了主管,主管让小明去了解一下备忘录模式,使用备忘录模式就可以完成这个功能,于是小明去搜集了一下备忘录的资料,然后将这个模式迅速掌握并应用到了新的功能上
定义
在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样就可以将该对象恢复到原先保存的状态
角色
- 发起人
- 备忘录
- 管理角色
用备忘录实现功能
通过备忘录模式的类图和角色,我们来实现一下我们的程序。首先,我们要定义我们的备忘录类,他记录了具体的状态
public interface IMemento {
}
public class Memento implements IMemento {
private int progress;
public Memento(int progress) {
this.progress = progress;
}
public int getProgress() {
return progress;
}
public void setProgress(int progress) {
this.progress = progress;
}
}
我们需要保存的是游戏的进度,所以我们游戏进度类是发起人,它来定义游戏进度类中哪些状态需要保存
游戏状态类,也就是我们的发起者:
public class Originator {
int progress;
public Originator() {
}
public int getProgress() {
return progress;
}
public void setProgress(int progress) {
this.progress = progress;
}
public Memento createMemento() {
return new Memento(this.progress);
}
public void restoreMemento(IMemento memento) {
this.setProgress(((Memento) memento).getProgress());
}
}
另外,我们还需要一个类来管理我们这些状态,可以根据实际需求来指定这个管理角色的管理形式,我们使用一个Map来管理,这样可以保存多个状态
public class Caretaker {
Map<String, IMemento> mementos;
public Caretaker() {
mementos = new HashMap<>();
}
public IMemento getMemento(String name) {
return mementos.get(name);
}
public void addMemento(String name, Memento memento) {
this.mementos.put(name, memento);
}
}
现在我们来使用这个备忘录,帮助我们完成状态的恢复
public class Client {
public static void main(String[] args) {
Originator originator = new Originator();
originator.setProgress(1);
System.out.println("当前进度 " + originator.getProgress());
Caretaker caretaker = new Caretaker();
caretaker.addMemento("进度一", originator.createMemento());
originator.setProgress(2);
System.out.println("当前进度 " + originator.getProgress());
originator.setProgress(3);
System.out.println("当前进度 " + originator.getProgress());
caretaker.addMemento("进度三", originator.createMemento());
originator.restoreMemento(caretaker.getMemento("进度一"));
System.out.println("当前进度 " + originator.getProgress());
originator.restoreMemento(caretaker.getMemento("进度三"));
System.out.println("当前进度 " + originator.getProgress());
}
}
最初时,游戏进度为1,调用游戏进度生成方法,也就是发起者产生一个此刻状态下的备忘录,并且将它保存到我们的Caretaker,名字为进度一
,然后们游戏进度改变,从2再到3,我们只在1和3的时候生成了备忘录,然后将它保存到了Caretaker,然后在状态3时我们恢复到了状态1,再恢复到了3
执行结果:
当前进度 1
当前进度 2
当前进度 3
当前进度 1
当前进度 3
备忘录和发起者
管理角色的功能很清晰,我们看看备忘录和发起者,发起者就是我们需要保存和恢复的,具体的备忘录也是由发起者产生的,备忘录里面需要存储的是由实际的需求来制定的,比如,有一些属性和状态无关,我们就不需要保存。备忘录模式比起其他模式算是比较简单的,不管是使用还是实现,但是它也有自己明显的优缺点:
优点:
- 当发起人角色中的状态改变时,有可能这是个错误的改变,我们使用备忘录模式就可以把这个错误的改变还原。
- 备份的状态是保存在发起人角色之外的,这样,发起人角色就不需要对各个备份的状态进行管理。
缺点:
- 在实际应用中,备忘录模式都是多状态和多备份的,发起人角色的状态需要存储到备忘录对象中,对资源的消耗是比较严重的。