1、引入
许多玩过游戏的朋友知道,有些游戏有种堪称bug的功能-存档,在遇到不顺情况时可以重新读取存档,返回先前存档的时间点重新来过。
而Memento模式正是一种可以实现存档的设计模式。
2、示例
设计以下一款游戏:
- 游戏者会投骰子,当投到1时金钱加100,2时金钱减一半,6时获得道具水果,其他什么都不会发生。
- 然而我们的游戏者却采取“卑鄙”的策略,当他的金钱增加时会存档,大量减少时会重新读档。
2.1、存档类Memento
public class Memento {
int money;
ArrayList fruits;
public int getMoney() {
return money;
}
public Memento(int money) {
this.money = money;
fruits=new ArrayList<>();
}
void addFruit(String fruit) {
fruits.add(fruit);
}
List getFruit() {
return fruits;
}
}
2.2、游戏类Gamer
public class Gamer {
private int money;
private List fruits=new ArrayList();
private Random random=new Random();
private static String[] fruitName={"苹果","葡萄","香蕉","橘子"};
public Gamer(int money) {
this.money = money;
}
public int getMoney() {
return money;
}
public void bet() {
int dice=random.nextInt(6)+1;
if (dice == 1) {
money+=100;
System.out.println("所持金钱增加100.");
} else if (dice == 2) {
money/=2;
System.out.println("所持金钱减半.");
} else if (dice == 6) {
String f = getFruit();
System.out.println("获得水果(" + f + ").");
fruits.add(f);
} else {
System.out.println("什么事都没有发生");
}
}
//存档
public Memento createMemento() {
Memento m=new Memento(money);
Iterator iterator = fruits.iterator();
while (iterator.hasNext()) {
String f=(String) iterator.next();
if (f.startsWith("好吃的")) {
m.addFruit(f);
}
}
return m;
}
//读档
public void restoreMemento(Memento memento) {
this.money=memento.money;
this.fruits=memento.fruits;
}
@Override
public String toString() {
return "Gamer{" +
"money=" + money +
", fruits=" + fruits +
", random=" + random +
'}';
}
private String getFruit() {
String prefix="";
if (random.nextBoolean()) {
prefix="好吃的";
}
return prefix+fruitName[random.nextInt(fruitName.length)];
}
}
2.3、测试
public class Main {
public static void main(String[] args) {
Gamer gamer = new Gamer(100);
Memento memento = gamer.createMemento();//存档
for (int i = 0; i < 100; i++) {
System.out.println("=========="+i);
System.out.println("当前状态:"+gamer);
gamer.bet();//进行游戏
System.out.println("所持金钱为"+gamer.getMoney()+"元");
if (gamer.getMoney() > memento.getMoney()) {
System.out.println("所持金钱增加,存档");
memento=gamer.createMemento();
} else if(gamer.getMoney()< memento.getMoney()/2) {
System.out.println("所持金钱减少许多,读档");
gamer.restoreMemento(memento);
}
}
}
}
运行结果(部分):
3、tips
- 这里实现的存档功能较为简单,应用上的存档功能往往涉及到IO以及一定存储格式
- 应用Memento模式,可以实现
- Undo
- Redo
- History
- SnapShot