Java设计模式之备忘录模式

 更新时间:2023年12月29日 10:04:54   作者:理想万岁万万岁  
这篇文章主要介绍了Java设计模式之备忘录模式,备忘录模式(Memento Pattern),属于行为型设计模式,目的是用于保存一个对象在某一时刻的状态,以便于在将来某个时刻根据此状态恢复该对象,需要的朋友可以参考下

一、介绍

备忘录模式(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);
    }
}

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

在这里插入图片描述

五、总结

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

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

到此这篇关于Java设计模式之备忘录模式的文章就介绍到这了,更多相关Java备忘录模式内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • JVM教程之Java代码编译和执行的整个过程(二)

    JVM教程之Java代码编译和执行的整个过程(二)

    这篇文章主要介绍了JVM学习笔记第二篇,关于Java代码编译和执行的整个过程,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-03-03
  • struts2实现简单文件下载功能

    struts2实现简单文件下载功能

    这篇文章主要为大家详细介绍了struts2实现简单文件下载功能,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-01-01
  • JVM中堆内存和栈内存的区别

    JVM中堆内存和栈内存的区别

    本文主要介绍了JVM中堆内存和栈内存的区别,具有很好的参考价值,下面跟着小编一起来看下吧
    2017-02-02
  • 解决springboot启动成功,但访问404的问题

    解决springboot启动成功,但访问404的问题

    这篇文章主要介绍了解决springboot启动成功,但访问404的问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-07-07
  • Java中进程与线程的区别

    Java中进程与线程的区别

    这篇文章主要介绍了Java进程与线程的区别,进程(Process)是操作系统分配资源的基本单位,线程(Thread)是操作系统能够进行运算调度的基本单位,下文更多两者区别。需要的小伙伴可以参考一下
    2022-05-05
  • 三道java新手入门面试题,通往自由的道路--锁+Volatile

    三道java新手入门面试题,通往自由的道路--锁+Volatile

    这篇文章主要为大家分享了最有价值的3道多线程面试题,涵盖内容全面,包括数据结构和算法相关的题目、经典面试编程题等,对hashCode方法的设计、垃圾收集的堆和代进行剖析,感兴趣的小伙伴们可以参考一下
    2021-07-07
  • 详解Spring整合mybatis--Spring中的事务管理(xml形式)

    详解Spring整合mybatis--Spring中的事务管理(xml形式)

    这篇文章主要介绍了Spring整合mybatis--Spring中的事务管理(xml形式),本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-11-11
  • SpringBoot整合Security实现权限控制框架(案例详解)

    SpringBoot整合Security实现权限控制框架(案例详解)

    Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框,是一个重量级的安全管理框架,本文给大家介绍的非常详细,需要的朋友参考下吧
    2021-08-08
  • springMVC中RestTemplate传值接值方法

    springMVC中RestTemplate传值接值方法

    今天小编就为大家分享一篇springMVC中RestTemplate传值接值方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-08-08
  • Springboot整合FreeMarker的实现示例

    Springboot整合FreeMarker的实现示例

    本文主要介绍了Springboot整合FreeMarker的实现示例,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-02-02

最新评论