设计模式之备忘录模式

一、介绍

备忘录模式(Memento Pattern),属于行为型设计模式。目的是用于保存一个对象在某一时刻的状态,以便于在将来某个时刻根据此状态恢复该对象。

在我们日常生活中,备忘录的使用十分频繁。比如,有一个事情我们完成了35%的进度,这时有另一件更重要的事情需要处理,那么我们需要对这个已完成35%的事情进行记录(做了哪些事情,做到什么程度等),当那个更重要的事情完成后,就可以根据记录的内容(做了哪些事情,做到什么程度等)继续处理这件事情,而不至于因为忘记处理进度而导致重复或疏漏,这个记录的过程就是备忘。

另一个十分鲜活的例子就是,我们经常在对一些东西进行计数时被其他人说话而打断,当你回答对方后自己却突然忘记数到哪里了,如果你在说话前已经数了相当长一段时间,那此时你可能不得不从0重新开始计数。当应用备忘录时,无论你的计数达到什么程度,在别人和你说话时,你先将当前计数保存记录下来,在谈话完成后,再继续计数即可,以此避免从0重新开始计数。

当我们系统中存在一个对象,

下面是备忘录模式的概念解释:

在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。

二、应用举例

根据我们在介绍中的描述,我们应该明白了备忘录模式的本质其实就是对象状态的保存和读取。不难发现,备忘录模式的应用到处可见

  • 几乎所有的软件

    在我们使用的所有软件无论是桌面端还是网页端,只要有保存功能,就都是备忘录模式的体现。

    比如,我们使用txt文本文档编辑文本,在编辑的过程中任意时刻我们都可以使用ctrl+s对其保存,当再次打开该txt文档时,展示的就是我们最后一次保存时的文本,这种备忘的介质就是硬盘

    再比如,我们在某一个网站中对个人信息进行编辑时,当按下保存按钮时,网页会发起网络请求,将我们编辑的个人信息发送到远程服务器,当再次打开个人信息页面进行查看或编辑时,网页会再次向远程服务器发起请求获取我们上一次保存个人信息。这种备忘的介质就是远程数据库

  • java序列化

    java的序列化和反序列化过程也是备忘录模式的体现。其中,序列化的过程就相当于对一个对象状态的保存,反序列化的过程就相当于对以保存的对象状态进行恢复。

三、基本角色

在标准的备忘录模式中,包含以下三个角色:

  • Memento

    保存对象的内部状态。即备忘录本身。而既然是备忘录,自然有两个最基本的方法来保存和获取其内部保存的状态:getState()setState()

    存储源发器对象的状态。备忘录对象可以包括一个或多个状态属性,源发器可以根据需要保存和恢复状态。

  • Originator

    创建备忘录,并保存指定对象的状态。即备忘录管理者。作为备忘录的管理者,自然在其内部保存着多个备忘(mementoList)和对应的添加删除方法(add(memento)remove(memento))。

    需要保存和恢复状态的对象。它创建一个备忘录对象,用于存储当前对象的状态,也可以使用备忘录对象恢复自身的状态。

  • Caretaker

    从备忘录中读取对象的状态并恢复对象。有了备忘录管理者,我们对备忘录的操作应转移到管理者上,通过备忘录管理者存取备忘录中的状态。

    负责保存备忘录对象,但不能修改备忘录对象的内容。它可以存储多个备忘录对象,并决定何时将备忘录恢复给源发器。

注意:一般情况下,备忘录模式无需抽象组件,但究竟需不需要抽象类根据实际情况来定。

备忘录的通用UML图如下所示

在这里插入图片描述

四、代码演示

下面我们通过代码对上面基本角色的分析进行演示

  • 备忘录类Memento

    public class Memento {
    
        // 对象某一时刻的状态
        private String state;
    
        // 获取对象的状态
        public String getState() {
            return state;
        }
    
        // 保存对象的状态
        public void setState(String state) {
            this.state = state;
        }
    }
    
  • 备忘录管理员类Originator

    public class Originator {
    
        // 备忘录集合
        private final List<Memento> mementoList;
    
        public Originator() {
            // 对备忘录集合进行初始化
            this.mementoList = new ArrayList<>();
        }
    
        // 保存对象某一状态到备忘录
        public void saveState(String state) {
            Memento memento = new Memento();
            memento.setState(state);
            mementoList.add(memento);
        }
    
        // 获取某一备忘录并将其移除
        public Memento getMemento(int index) {
            return mementoList.remove(index);
        }
    }
    
    
  • 读取状态类Caretaker

    public class Caretaker {
    
        // 备忘录管理者
        private final Originator originator;
    
        // 备忘录管理者的初始化
        public Caretaker(Originator originator) {
            this.originator = originator;
        }
    
        // 获取某个备忘录中对象的状态
        public String getState(Integer index) {
            return originator.getMemento(index).getState();
        }
    }
    
  • 客户端测试代码

    public class MementoDemo {
    
        public static void main(String[] args) {
            // 将对象的状态交给备忘录管理员通过备忘录管理
            Originator originator = new Originator();
            originator.saveState("第一个字符串");
            originator.saveState("第二个字符串");
            originator.saveState("第三个字符串");
            originator.saveState("第四个字符串");
            originator.saveState("第五个字符串");
    
            // 读取备忘录中对象的状态
            Caretaker caretaker = new Caretaker(originator);
            String state5 = caretaker.getState(4);
            System.out.println(state5);
    
            String state4 = caretaker.getState(3);
            System.out.println(state4);
    
            String state3 = caretaker.getState(2);
            System.out.println(state3);
    
            String state2 = caretaker.getState(1);
            System.out.println(state2);
    
            String state1 = caretaker.getState(0);
            System.out.println(state1);
    
        }
    }
    

运行以上代码,得到以下输出

在这里插入图片描述

五、总结

备忘录模式给我们提供了一种可以恢复状态的机制,可以使用户能够比较方便地回到某个历史的状态,在此同时,备忘录模式也实现了信息的封装,使得用户不需要关心状态的保存细节。

但是,备忘录模式的可扩展性并不是很好,每一种对象都需要对应一种备忘录,这将会导致类的数量膨胀,对内存无疑是一种考验。



纸上得来终觉浅,绝知此事要躬行。

————————我是万万岁,我们下期再见————————

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

理想万岁万万岁

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值