1.备忘录模式定义
在不破坏封装的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样可以在以后将对象恢复到原先保存的状态;
1.1 备忘录模式的优缺点
优点
- 提供了一种状态恢复的实现机制,使得用户可以方便的回到一个特定的历史步骤,当新的状态无效或者存在问题的时候,可以使用暂时存储起来的备忘录将状态恢复;
- 备忘录实现了对信息的封装,一个备忘录对象是一种发起者对象状态的表示,不会被其他代码所改动;
缺点
- 资源消耗过大,如果需要保存的发起者类的成员变量比较多,就不可避免的需要占用大量的存储空间,每保存一次对象的状态都需要消耗一定的系统资源;
1.2 备忘录模式的使用场景
- 需要保存一个对象在某一时刻的状态时,可以使用备忘录模式;
- 不希望外界直接访问对象内部状态时;
2.备忘录模式的原理
- 发起人(Originator):状态需要被记录的元对象类,记录当前时刻的内部状态信息,提供创建备忘录和恢复备忘录数据的功能,它可以访问备忘录里的所有信息;
- 备忘录(Memento):负责存储发起人的内部状态,在需要的时候提供这些内部状态给发起人;
- 看护人(Caretaker):对备忘录进行管理,提供保存与获取备忘录的功能,但其不能对备忘录的内容进行访问与修改;
3.备忘录模式的实现
【实例】
一个简单的吃金币的游戏,玩家通过掷骰子来决定下一状态,点数为1、3、5时金币增加对应数,点数为2、4、6时玩家减少对应金币,当金币为小于等于0时游戏重新开始;
【代码】
备忘录:记录玩家的状态
public class Memento {
int money; //所持金钱
//构造函数
Memento(int money) {
this.money = money;
this.fruits = new ArrayList();
}
//获取当前玩家所有的金钱
int getMoney() {
return money;
}
}
发起人——玩家
public class Player {
private int money; //所持金钱
private Random random = new Random(); //随机数对象
//构造方法
public Player(int money) {
this.money = money;
}
//获取当前所持有的金钱
public int getMoney() {
return money;
}
//掷骰子游戏
public void yacht(){
int dice = random.nextInt(6) + 1; //掷骰子
switch(dice){
case 1:
case 3:
case 5:
money += dice;
break;
case 2:
case 4:
case 6:
money -= dice;
break;
default:
break;
}
}
//拍摄快照
public Memento createMemento(){
Memento memento = new Memento(money);
return memento;
}
//撤销方法
public void restore(Memento memento){
this.money = memento.money;
}
@Override
public String toString() {
return "Player{" +
"money=" + money +
'}';
}
}
看护人——客户端
public class MainApp {
public static void main(String[] args) throws InterruptedException {
Player player = new Player(100); //最初所持的金钱数
Memento memento = player.createMemento(); //保存最初状态
for (int i = 0; i < 100; i++) {
//显示扔骰子的次数
System.out.println("=====" + i);
//显示当前状态
System.out.println("当前状态: " + player);
//开启游戏
player.yacht();
System.out.println("所持有的金钱为: " + player.getMoney() + " 元");
//决定如何操作Memento
if(player.getMoney() > 0){
System.out.println("赚到金币,保存当前状态,继续游戏!");
memento = player.createMemento();
}else {
System.out.println("所持金币不足,游戏重新开始!");
player.restore(memento);
}
Thread.sleep(1000);
System.out.println("");
}
}
}