玩游戏我们都知道有个东西叫自动存档
,在我们遇到大Boss要打的时候,更是如此,一定要存档!
如果没有存档,死了就要你重新开始,如果是些大型游戏,已经花费了你很多时间,遇到大Boss,然后你被打死了,又没有存档,估计你就想直接把这个游戏卸载了。
有时偷懒,还去下载别人的通关档案回来覆盖本地的。
哈,我就曾经做过!还有一些已经刷满无限金币等的存档!
曾经还遇到过必须被大Boss打死才能继续的剧情,但因为外挂太牛逼,活生生把大Boss给打死了!搞到后面都没法继续,只能自己手动滚回某个档案,装怂,去被boss虐下。
所以很好理解,这个自动存档会保存我们当前的角色的状态,然后如果被大Boss打死了,就自动恢复到这个存档点状态,我们还可以继续去打大Boss,直到我们过关为止。
很显然就是用备忘录模式来做,也有翻译为纪念品
的。
代码实现
现在我们先来准备下我们的主角
public class User {
private int blood;//血量
private int level;//等级
private int force;//攻击力
private String name;
private int sex;
public User(int blood, int level, int force, String name, int sex) {
this.blood = blood;
this.level = level;
this.force = force;
this.name = name;
this.sex = sex;
}
public Memento saveState() {
return new Memento(this.blood, this.level, this.force);
}
public void restoreState(int blood, int level, int force) {
this.blood = blood;
this.level = level;
this.force = force;
}
public void setBlood(int blood) {
this.blood = blood;
}
}
我们的角色一般都有血量,等级和攻击力,还有名字和性别的属性。
现在我们设置只保存血量,等级和攻击力,对于名字和性别这个就不做保存,毕竟不可能打了下BOSS,就连名字和性别都换了…
所以我们来看下我们每次存档时候保存的信息内容的Memento
public class Memento {
private long time;
private int blood;
private int level;
private int force;
public Memento(int blood, int level, int force) {
this.time = System.currentTimeMillis();
this.blood = blood;
this.level = level;
this.force = force;
}
public long getTime() {
return time;
}
public int getBlood() {
return blood;
}
public int getLevel() {
return level;
}
public int getForce() {
return force;
}
}
保存了血量,等级和攻击力,还有时间,当然需要时间啦。
接着就是一个来管理这对档案的一个类Caretaker
public class Caretaker {
private List<Memento> mementoList = new ArrayList<>();
public Memento getLastMemento() {
return mementoList.get(mementoList.size() - 1);
}
public void addMemento(Memento memento) {
mementoList.add(memento);
}
}
他的作用是保存我们的档案记录,包括持久化到本地等操作。
但我们这里简单化了,直接是就用一个List来保存就好了,毕竟只是demo。
当然你也可以只用一个Memento来保存,毕竟也有些游戏限制只能有一个档案,新的会覆盖旧的档案。
有了这些准备,我们就可以来模拟下存档这个过程了
public class Client {
public static void main(String[] args) {
User user = new User(100, 99, 999, "jack", 0);
Caretaker caretaker = new Caretaker();
//在打boss前我们存档
caretaker.addMemento(user.saveState());
//被boss打死了,血量为0
user.setBlood(0);
//好在我们存档了,我们要恢复到最后保存的状态
Memento memento = caretaker.getLastMemento();
//好,我们又原地满血复活,可以继续去打Boss啦!
user.restoreState(memento.getBlood(), memento.getLevel(), memento.getForce());
}
}
类图
这里的caretaker负责人就是来保存备忘录的,不会对备忘录的内容进行操作!
而那个Memento就是负责保存具体的内容
然后那个Originator原发器,是用于创建一个备忘录的,同时备忘录恢复内部状态的,对应于User。
这个可以用在我们的状态模型中去,如果某一部操作错误了,可以回滚回去。
后记
使用这个备忘录可能代价很高,因为他必须拷贝并存储大量的信息,或者用户频繁的存档和恢复的时候,也是不小问题,当然我们如果可以的话,可以考虑下增量存储的。
另外对于只支持一个档案的,可以考录下面这种简单的方式。
public class UserCloneable implements Cloneable {
private UserCloneable backup;
private int blood;//血量
private int level;//等级
private int force;//攻击力
private String name;
private int sex;
public UserCloneable(int blood, int level, int force, String name, int sex) {
this.blood = blood;
this.level = level;
this.force = force;
this.name = name;
this.sex = sex;
}
public void createState() throws CloneNotSupportedException {
this.backup = (UserCloneable) this.clone();
}
public void restoreState() {
setState(this.backup.blood, this.backup.level, this.backup.force);
}
private void setState(int blood, int level, int force) {
this.blood = blood;
this.level = level;
this.force = force;
}
public void setBlood(int blood) {
this.blood = blood;
}
}
利用原型模型,简单的在类里面加多一个镜像!绝对的懒人方案。
不过请注意在写原型模型时候提到的浅拷贝
和深拷贝
的问题。