• 21、设计模式之备忘录模式(Memento)


    一、什么是备忘录模式
    备忘录模式又称快照模式,是一种行为型设计模式。它可以在不破坏封装性的前提下捕获一个对象的内部状态,并在对象之外保存这个状态,以便在需要的时候恢复到原先保存的状态。

    二、角色组成

    源发器(Originator):需要保存和恢复状态的对象。它创建一个备忘录对象,用于存储当前对象的状态,也可以使用备忘录对象恢复自身的状态。
    备忘录(Memento):存储源发器对象的状态。备忘录对象可以包括一个或多个状态属性,源发器可以根据需要保存和恢复状态。
    管理者(Caretaker):负责保存备忘录对象,但不能修改备忘录对象的内容。它可以存储多个备忘录对象,并决定何时将备忘录恢复给源发器。

    三、优缺点
    优点:

    状态保存与恢复:备忘录模式可以帮助我们保存对象的状态,并在需要时恢复到之前的状态。这在某些情况下非常有用,比如撤销操作或者程序崩溃后的恢复。
    封装性和隔离性:可以确保对象的状态保存在备忘录对象中,而不会暴露给其他对象。这为对象的封装性和隔离性提供了保护,使得对象的状态变化对其他对象是透明的。
    缺点:

    内存占用:可能引起较大的内存占用,特别是当对象的状态较多且状态改变频繁时。每个备忘录对象都需要保存一份完整的状态,如果状态较多或者备忘录对象较多,可能会消耗大量内存。
    性能开销:备忘录模式涉及到创建、存储和恢复状态的操作,这些操作可能引起一定的性能开销。特别是在状态较大或者对象较复杂的情况下,备忘录模式的性能可能会受到影响。
    四、应用场景
    浏览器的回退:当我们点击回退箭头时,浏览器会回退到上一个被浏览的网站,以显示之前访问的页面。

    文本编辑器的撤销:如果误删了一些内容或者想恢复之前的修改,可以进行撤销操作。

    数据库事务管理:当执行数据库操作时,我们可以将当前数据库的状态保存到备忘录对象中,在回滚操作或者发生错误时,可以使用备忘录对象恢复到之前的数据库状态。

    五、代码实现
    下面以文本编辑器为例,解释一下备忘录模式。

    用户可以在编辑器中输入文本,并允许回退到之前的编辑状态。其中Editor类代表文本编辑器(源发器),它具有保存和恢复文本内容的功能。EditorMemento类表示备忘录对象,用于保存Editor的状态。History类作为管理者,负责保存和管理备忘录对象。

    5.0 UML类图
    在这里插入图片描述
    5.1 EditorMemento——备忘录(Memento)

    /**
     * 
     * 1.备忘录(Memento):备忘录,保存编辑器的状态
     * 定义:存储源发器对象的状态。备忘录对象可以包括一个或多个状态属性,源发器可以根据需要保存和恢复状态。
     */
    public class EditorMemento {
        //文本内容 (可以是属性、也可以是对象)
        private  String content;
     
        public EditorMemento(String content) {
            this.content = content;
        }
     
        public String getContent() {
            return content;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    5.2 Editor——源发器(Originator)

    /**
     * 
     * 2.源发器(Originator):文本编辑器
     * 定义:需要保存和恢复状态的对象。它创建一个备忘录对象,用于存储当前对象的状态,也可以使用备忘录对象恢复自身的状态。
     */
    public class Editor {
        //内容(可以是属性、也可以是对象)
        private String content;
     
        public void setContent(String content) {
            this.content = content;
        }
     
        public String getContent() {
            return content;
        }
     
        // 创建备忘录对象,保存当前状态
        public EditorMemento createMemento() {
            return new EditorMemento(content);
        }
     
        // 恢复备忘录对象保存的状态
        public void restoreMemento(EditorMemento memento) {
            content = memento.getContent();
        }
     
    }
    
    • 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

    5.3 History——管理者(Caretaker)

    /**
     * 
     * 3.管理者(Caretaker):历史记录
     * 定义:负责保存备忘录对象,但不能修改备忘录对象的内容。它可以存储多个备忘录对象,并决定何时将备忘录恢复给源发器。
     */
    public class History {
        //备忘录可以保存多个状态
        private final List<EditorMemento> mementos = new ArrayList<>();
     
        // 保存备忘录对象的状态
        public void push(EditorMemento memento) {
            mementos.add(memento);
        }
     
        // 弹出(移除)最近保存的备忘录对象,并返回它
        public EditorMemento pop() {
            int lastIndex = mementos.size() - 1;
            EditorMemento lastMemento = mementos.get(lastIndex);
            mementos.remove(lastIndex);
            return lastMemento;
        }
     
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    5.4 testMemento

    /**
     * 
     * 备忘录模式测试类
     */
    @SpringBootTest
    public class TestMemento {
     
        @Test
        void testMemento(){
            //创建文本编辑器(源发器)
            Editor editor = new Editor();
            //创建管理者
            History history = new History();
            // 编辑文本并保存状态
            editor.setContent("Hello");
            history.push(editor.createMemento());
     
            // 编辑更多文本并再次保存状态
            editor.setContent("Hello, Java!");
            history.push(editor.createMemento());
     
            editor.setContent("Hello,world!");
            System.out.println("当前内容: " + editor.getContent());
     
            // 恢复之前的状态
            editor.restoreMemento(history.pop());
            System.out.println("恢复后上一次内容: " + editor.getContent());
     
            editor.restoreMemento(history.pop());
            System.out.println("恢复后上二次内容: " + editor.getContent());
        }
    }
    
    • 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

    在这里插入图片描述
    六、总结
    备忘录模式提供了一种灵活的机制来保存和恢复对象的状态,对于需要撤销、恢复或者状态管理的场景非常有用。然而,它也可能引起较大的内存占用和一定的性能开销,需要在使用之前慎重考虑。以下场景可以作为参考:

    撤销和恢复功能:可以通过保存对象的历史状态来实现撤销和恢复功能,比如文本编辑器、绘图应用程序或任务管理器。
    版本控制:如果你的应用程序需要跟踪对象状态的历史记录,并支持版本控制功能,备忘录模式可以帮助实现这种需求。例如,可以使用备忘录模式来实现文档的版本控制。
    多阶段事务:备忘录模式可以用于实现多阶段事务的状态管理。在一个事务中,可能需要保存中间状态,以便在需要时回滚到之前的状态。

  • 相关阅读:
    Java 基于 SPringBoot 的幼儿园管理系统,附源码、数据库
    某客户管理系统Oracle RAC节点异常重启问题详细分析记录
    JVM篇---第三篇
    汽车视频智能剪辑解决方案,满足用户对高品质汽车视频的追求
    在 Transformers 中使用对比搜索生成可媲美人类水平的文本 🤗
    DayDayUp:计算机技术与软件专业技术资格证书之《系统集成项目管理工程师》课程讲解之项目信息文档管理与配置管理
    Go语言中的锁与管道的运用
    域名注册查询流程
    丹青映画董事长唐丹青于元宇宙产业资源对接会上进行精彩演讲
    SpringBoot+ECharts+Html 字符云/词云案例详解
  • 原文地址:https://blog.csdn.net/weixin_45817985/article/details/136678109