备忘录模式

编程中的‘后悔药’-备忘录模式

模式简介

再不破坏封闭的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样,以后就可以将该对象恢复到原先保存状态。

应用场景

  1. 需要保存一个对象在某一时刻的状态或者部分状态
  2. 如果用一个接口来让其他对象得到这些状态,将会暴露对象的实现细节并破坏对象的封装性,一个对象不希望外接直接访问其内部状态,通过中间对象可以间接访问其内部状态

简单实现

使命召唤游戏

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
package MementoPattern;

//使命召唤游戏
public class CallOfDuty {
    private int mCheckpoint=1;
    private int mLifeValue=100;
    private String mWeapon="沙漠之鹰";
    //玩游戏
    public void play(){
        System.out.println("玩游戏:"+String.format("第%d关",mCheckpoint)+"奋战杀敌中");
        mLifeValue-=10;
        System.out.println("进度升级了");
        mCheckpoint++;
        System.out.println("到达"+String.format("第%d关",mCheckpoint));
    }
    //退出游戏
    public void quit(){
        System.out.println("----------");
        System.out.println("退出游戏前属性:"+this.toString());
        System.out.println("退出游戏");
        System.out.println("----------");
    }
    //创建备忘录
    public Memoto createMemoto(){
        Memoto memoto=new Memoto();
        memoto.mCheckpoint=mCheckpoint;
        memoto.mLifeValue=mLifeValue;
        memoto.mWeapon=mWeapon;
        return memoto;
    }
    //恢复游戏
    public void restore(Memoto memoto){
        this.mCheckpoint=memoto.mCheckpoint;
        this.mLifeValue=memoto.mLifeValue;
        this.mWeapon=memoto.mWeapon;
        System.out.println("恢复游戏后的属性:"+this.toString());
    }

    public int getmCheckpoint() {
        return mCheckpoint;
    }

    public void setmCheckpoint(int mCheckpoint) {
        this.mCheckpoint = mCheckpoint;
    }

    public int getmLifeValue() {
        return mLifeValue;
    }

    public void setmLifeValue(int mLifeValue) {
        this.mLifeValue = mLifeValue;
    }

    public String getmWeapon() {
        return mWeapon;
    }

    public void setmWeapon(String mWeapon) {
        this.mWeapon = mWeapon;
    }

    @Override
    public String toString() {
        return "CallOfDuty{" +
                "mCheckpoint=" + mCheckpoint +
                ", mLifeValue=" + mLifeValue +
                ", mWeapon='" + mWeapon + '\'' +
                '}';
    }
}

管理类:责管理备忘录

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
package MementoPattern;

//Caretaker 管理类,负责管理Memoto
public class Caretaker {
    Memoto memoto;//备忘录
    //存档
    public void archive(Memoto memoto){
        this.memoto=memoto;
    }
    //获取存档
    public Memoto getMemoto(){
        return memoto;
    }
}

备忘录类

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
package MementoPattern;
//备忘录类
public class Memoto {
    public int mCheckpoint;
    public int mLifeValue;
    public String mWeapon;

    @Override
    public String toString() {
        return "Memoto{" +
                "mCheckpoint=" + mCheckpoint +
                ", mLifeValue=" + mLifeValue +
                ", mWeapon='" + mWeapon + '\'' +
                '}';
    }
}

测试代码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
package MementoPattern;

public class Client {
    public static void main(String[] args) {
        //构建对象
        CallOfDuty callOfDuty=new CallOfDuty();
        //打游戏
        callOfDuty.play();

        Caretaker caretaker=new Caretaker();
        //游戏存档
        caretaker.archive(callOfDuty.createMemoto());
        //退出游戏
        callOfDuty.quit();
        //恢复游戏
        CallOfDuty game=new CallOfDuty();
        game.restore(caretaker.getMemoto());
    }
}

执行结果

xxx.png

总结

备忘录模式是在不破坏封装的条件下,通过备忘录对象(Memoto)存储另外一个对象内部状态的快照,在将来合适的时候把这个对象还原到存储起来的状态。

优点

  1. 给用户提供了一种可以恢复状态的机制,可以使用户能够比较方便的回到某个历史状态。
  2. 实现了信息的封装,使得用户不需要关心状态的保存细节

缺点

消耗资源,如果类的成员变量过多,势必会占用比较大的资源,而且每一次保存都会消耗一定的内存。