什么是备忘录模式
类似玩游戏时,需要有保存游戏和加载游戏的功能,我们需要记录某个时刻某个对象的状态信息,在必要时进行回滚到那个时刻的状态。
备忘录模式就是为某个对象(目标对象)专门创建一个类,用来保存它的状态信息。注意Memento模式的状态类只保存了目标对象的部分信息,而Prototype模式中的原型对象则是完整克隆了对象的所有信息。
示例
示例程序类似一个大富翁游戏,涉及类比较少,有玩家Gamer、专门用于表示玩家状态的Memento、还有测试类Main
玩家Gamer,属性有金额money、水果袋子fruits、骰子random。主要的行为就是3个,createMemento表示创建一个状态对象保存当前的金额和水果,restoreMemento表示将当前对象回滚到传入的状态,bet就是掷骰子,改变目标对象的状态。
public class Gamer {
private int money;
private List fruits = new ArrayList();
private Random random = new Random();
private static String[] fruitsname = {
"苹果", "葡萄", "香蕉", "橘子"
};
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("所持金钱增加了");
} 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 it = fruits.iterator();
while (it.hasNext()) {
String f = (String) it.next();
if (f.startsWith("好吃的")) {
m.addFruit(f);
}
}
return m;
}
public void restoreMemento(Memento memento) {
this.money = memento.money;
this.fruits = memento.getFruits();
}
public String toString() {
return "[money = " + money + ", fruits = " + fruits + "]";
}
private String getFruit() {
String prefix = "";
if (random.nextBoolean()) {
prefix = "好吃的";
}
return prefix + fruitsname[random.nextInt(fruitsname.length)];
}
}
状态Memento,主要就是将目标对象的状态信息保存下来。
// 表示Gamer(主人公)状态的类
public class Memento {
int money;
ArrayList fruits;
public Memento(int money) {
this.money = money;
this.fruits = new ArrayList();
}
public int getMoney() {
return money;
}
void addFruit(String fruit) {
fruits.add(fruit);
}
List getFruits() {
return (List) fruits.clone();
}
}
测试类,就是让玩家掷骰子,金额增加了就保存为最新的备份,如果钱少了就回滚上一个状态。
public class Main {
public static void main(String[] args) {
Gamer gamer = new Gamer(100);
Memento memento = gamer.createMemento();
for (int i = 0; i < 20; 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);
}
// 等待一段时间
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}