备忘录模式(Memoto)

381 阅读3分钟

定义

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

本质

保存和恢复内部状态。

登场角色

  • Originator(生成者)

    生成者角色会在保存自己的最新状态时生成纪念品角色。

  • Memento(纪念品)

    纪念品角色会将生成者角色的内部信息整合到一起,在纪念品角色中虽然保存了生成者角色的信息,但是不会向外部公开这些信息

  • Caretaker(负责人)

    当负责人角色想要保存当前生成者角色的状态时,会通知生成者角色,生成者角色在接收到通知时后会生成纪念品角色对象并将其返回给负责人角色,并且负责人角色会一直保存纪念品实例。

示例代码

/**
 * 生成者,即需要被保存的对象
 */
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 = mCheckPoint - 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());
    }

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



public class Memoto {
    public int mCheckPoint;
    public int mLifeValue;
    public String mWeapon;

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


/**
 * 负责管理备忘录Memoto
 */
public class CareTaker {
    Memoto memoto;

    public Memoto getMemoto() {
        return memoto;
    }

    public void setMemoto(Memoto memoto) {
        this.memoto = memoto;
    }
}


/**
 * 使用者
 */
public class Client {
    public static void main(String[] args){
        //构建游戏对象
        CallOfDuty callOfDuty = new CallOfDuty();
        //玩游戏
        callOfDuty.play();
        //游戏存档
        CareTaker careTaker = new CareTaker();
        careTaker.setMemoto(callOfDuty.createMemoto());
        //退出游戏
        callOfDuty.quit();
        //回复游戏
        CallOfDuty callOfDuty1 = new CallOfDuty();
        callOfDuty1.restore(careTaker.getMemoto());
    }
}

运行结果

玩游戏:第1关
进度升级
到达:第2关
==============
退出游戏前的属性:CallOfDuty{mCheckPoint=2, mLifeValue=-9, mWeapon='沙漠之鹰'}
退出游戏
==============
恢复后的游戏属性:CallOfDuty{mCheckPoint=2, mLifeValue=-9, mWeapon='沙漠之鹰'}

功能

在不破坏封装性的前提下,捕获一个对象的内部状态,以便在以后的某个时刻,可以将该对象恢复到备忘录所保存的状态,这也是备忘录模式的目的。

优点

  • 更好的封装性,通过使用备忘录对象,来封装生成者对象的内部状态,有效地保证了对生成者对象的内部状态的封装,不把生成者对象的内部实现细节暴露给外部。
  • 简化了生成器,将对象状态的保存,交给外部对象来处理。

缺点

  • 可能会导致高开销。因为备忘录模式是对对象的存储和恢复,它的基本实现方式就是缓存对象,这样一来,如果需要缓存的数据量比较大,或者是特别频繁的创建备忘录对象,开销会很大。

使用场景

  • 必须保存一个对象在某一时刻的全部或者部分状态,一遍在以后需要的时候,可以把对象恢复到之前的状态,可以使用备忘录模式。
  • 如果需要保存一个对象的内部状态,但是如果用接口来让其他对象直接得到这些状态信息,会破坏对象的封装性,这时可以使用备忘录模式。