设计模式之备忘录模式

2,912 阅读3分钟

备忘录模式

介绍

  • 是一种行为模式
  • 用于保存对象当前状态,并在之后恢复到此状态(后悔药)
  • 需要保证被保存的对象状态不能被外部访问,保证内部完整性,不向外透露

定义

  • 在不破坏封闭的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,以便恢复到原先保存的状态

使用场景

  • 需要保存一个对象在某一个时刻的状态或者部分状态

  • 如果用一个接口来让其他对象的到这些状态,将会暴露这个对象的实现细节并破坏对象的的封装性,一个对象不希望外界直接访问其内部状态,通过中间对象可以间接访问其内部状态

UML

说明

  1. Originator:负责创建一个备忘录,可以记录、恢复自身的内部状态。同事还可以根据需要决定Memento存储自身的那些状态

  2. Mement:备忘录角色,用于存储Originator的内部状态,并且可以防止Originator以外的对象访问Memento

  3. Caretaker: 负责存储备忘录,不能对备忘录的内容进行操作和访问,只能够将备忘录传递给其他对象

简单实现

1.备忘录类,用于记录游戏需要记录的详细信息

    /**
     * 备忘录类
     */
    public class Memoto {
        public int mCheckpoint;
        public int mLifeValue;
        public String mWeapon;

        @Override
        public String toString() {
            return "Memoto [mCheckpoint="+mCheckpoint+
                    " mLifeValue"+mLifeValue+
                    " mWeapon"+mWeapon+"]";
        }
    }

2.创建游戏类(Originator),实现游戏基本逻辑,其内部可以实现备忘录的创建以及获取,但是不实现存储以及恢复的逻辑

    /*
     * 使命召唤游戏演戏(Originator)
     */
    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());
        }

        @Override
        public String toString() {
            return "CallOfDuty [mCheckpoint="+mCheckpoint+
                    " mLifeValue"+mLifeValue+
                    " mWeapon"+mWeapon+"]";
        }
    }

3.Caretaker类的创建,实现游戏进度的存档以及恢复逻辑,但是不对实际的游戏数据进行操作

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

        //存档
        public void archive(Memoto memoto){
            this.memoto = memoto;
        }

        //获取存档
        public Memoto getMemoto(){
            return memoto;
        }
    }

4.Main函数的实现

    public class Main {

    public static void main(String[] args) {
        //构建游戏对象
        CallOfDuty callOfDuty = new CallOfDuty();
        //开始游戏
        callOfDuty.play();
        //构建caretaker,用于游戏存档
        Caretaker caretaker = new Caretaker();
        //通过游戏本身创建备忘录,caretaker执行存档操作
        caretaker.archive(callOfDuty.createMemoto());
        //退出游戏
        callOfDuty.quit();
        //重新开启游戏,并通过caretaker恢复游戏进度
        CallOfDuty callOfDuty1 = new CallOfDuty();
        callOfDuty1.restore(caretaker.getMemoto());
        }
    }

5.运行结果

    打游戏:第1关奋战杀敌中
    进度升级了
    到达第2关
    ---------------------
    退出前的属性:CallOfDuty [mCheckpoint=2 mLifeValue90 mWeapon沙漠之鹰]
    退出游戏
    ---------------------
    恢复后的游戏属性:CallOfDuty [mCheckpoint=2 mLifeValue90 mWeapon沙漠之鹰]
  • 总结:CallOfDuty在这里是Origintor角色,也就是需要存储数据的对象,这里并没有直接存储CallOfDuty对象,而是通过Memoto对CallOfDuty对象的数据进行存储,然后在存储Memoto对象,最终对Memoto对象的存取操作交给Caretaker对象。在整个过程中,对外屏蔽了对CallOfDuty角色的直接访问,满足对象状态存取功能的同时也是的该模块的结构保持清晰、整洁。

拓展

Android源码中备忘录设计模式的实现