设计模式行为型——备忘录模式

news2024/9/23 21:28:56

目录

什么是备忘录模式

备忘录模式的实现

备忘录模式角色

备忘录模式类图

备忘录模式举例

备忘录模式代码实现

备忘录模式的特点

优点

缺点

使用场景

注意事项

实际应用


什么是备忘录模式

        备忘录模式(Memento Pattern)又叫做快照模式(Snapshot Pattern)或Token模式(Token Pattern),属于行为型设计模式。在不破坏封闭的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态。

        备忘录模式提供了一种状态恢复的实现机制,使得用户可以方便地回到一个特定的历史步骤,当新的状态无效或者存在问题时,可以使用暂时存储起来的备忘录将状态复原,当前很多软件都提供了撤销操作,其中就使用了备忘录模式。

备忘录模式的实现

备忘录模式角色

  1. 原发器角色(Originator):负责创建一个备忘录,记录当前时刻的内部状态信息,提供创建备忘录和恢复备忘录数据的功能,实现其他业务功能,它可以访问备忘录里的所有信息。同时原发器还可以根据需要决定Memento存储Originator的那些内部状态。
  2. 备忘录角色(Memento):负责存储Originator对象的内部状态,并可以防止Originator以外的其他对象访问备忘录。备忘录有两个接口:Caretaker只能看到备忘录的窄接口,他只能将备忘录传递给其他对象。Originator却可看到备忘录的宽接口,允许它访问返回到先前状态所需要的所有数据。
  3. 管理者角色(Caretaker):管理者又称为负责人,它负责保存备忘录。在管理者类中可以存储一个或多个备忘录对象,它只负责存储对象,而不能修改对象(负责任类只提供备忘录对象的读写接口,不提供备忘录属性的读写接口),也无须知道对象的实现细节。管理者对象可以保存一个备忘录数组,从而实现原发器的多次撤销。其存储这些状态信息,除了原发器外其他对象都是不可以访问的,否则就违反了封装的原则。

        所以为了实现备忘录模式的封装,需要对备忘录的访问做些控制:

        对原发器:可以访问备忘录里的所有信息。
        对管理者:不可以访问备忘录里面的数据,但是他可以保存备忘录并且可以将备忘录传递给其他对象。
        其他对象:不可访问也不可以保存,它只负责接收从负责人那里传递过来的备忘录同时恢复原发器的状态。

        所以就备忘录模式而言理想的情况就是只允许生成该备忘录的那个原发器访问备忘录的内部状态。

备忘录模式类图

备忘录模式举例

        要开发一个简单的草稿箱功能,假设只保留文档标题和正文,那么文档标题和正文就属于原发器角色,还需要创建一个文章备忘录,和一个草稿箱作为管理者角色,保存历史文章信息。

        文章备忘录 包含了要被恢复的对象的状态。编辑器 创建并在 文章备忘录 对象中存储状态。草稿箱 对象负责从 文章备忘录 中恢复对象的状态。

备忘录模式代码实现

原发器角色

package com.common.demo.pattern.memento;

/**
 * @author Evan Walker 昂焱数据: https://www.ayshuju.com
 * @version 1.0
 * @desc 原发器角色 - 编辑器
 * @date 2023/08/05 10:26:52
 */
public class Editor {

    private String title;

    private String content;

    public Editor() {
    }

    public Editor(String title, String content) {
        this.title = title;
        this.content = content;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }

    public ArticleMemento saveToMemento(){
        ArticleMemento articleMemento = new ArticleMemento(this.title, this.content);
        return articleMemento;
    }

    public void undoFromMemento(ArticleMemento articleMemento){
        this.title = articleMemento.getTitle();
        this.content = articleMemento.getContent();
    }

    @Override
    public String toString() {
        return "Editor{" +
                "title='" + title + '\'' +
                ", content='" + content + '\'' +
                '}';
    }
}

备忘录角色

package com.common.demo.pattern.memento;

/**
 * @author Evan Walker 昂焱数据: https://www.ayshuju.com
 * @version 1.0
 * @desc 备忘录角色 - 文章
 * @date 2023/08/05 10:28:21
 */
public class ArticleMemento {
    // 标题
    private String title;
    // 正文
    private String content;

    public ArticleMemento() {
    }

    public ArticleMemento(String title, String content) {
        this.title = title;
        this.content = content;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }
}

管理者角色

package com.common.demo.pattern.memento;

import java.util.Stack;

/**
 * @author Evan Walker 昂焱数据: https://www.ayshuju.com
 * @version 1.0
 * @desc 管理员角色  - 草稿箱
 * @date 2023/08/05 10:30:41
 */
public class DraftsBox {

    // 存储 - 后进先出
    private final Stack<ArticleMemento> STACK = new Stack<>();

    public ArticleMemento getMemento() {
        ArticleMemento articleMemento = STACK.pop();
        return articleMemento;
    }

    public void addMemento(ArticleMemento articleMemento) {
        STACK.push(articleMemento);
    }
}

测试类

package com.common.demo.pattern.memento;

/**
 * @author Evan Walker 昂焱数据: https://www.ayshuju.com
 * @version 1.0
 * @desc 测试类
 * @date 2023/08/05 10:31:12
 */
public class Test {
    public static void main(String[] args) {
        DraftsBox draftsBox = new DraftsBox();

        Editor editor = new Editor("初始化", "首次发表");
        ArticleMemento articleMemento = editor.saveToMemento();
        draftsBox.addMemento(articleMemento);
        System.out.println("--------第一次编辑,保存草稿之后,信息如下:---------");
        System.out.println(editor);

        editor.setTitle("第一次修改");
        editor.setContent("首次发表后,第一次修改");
        ArticleMemento articleMemento1 = editor.saveToMemento();
        draftsBox.addMemento(articleMemento1);
        System.out.println("--------第一次修改,保存草稿之后,信息如下:---------");
        System.out.println(editor);

        editor.setTitle("第二次修改");
        editor.setContent("首次发表后,第二次修改");
        System.out.println("--------第一次修改,还没保存草稿,信息如下:---------");
        System.out.println(editor);

        System.out.println("-------撤销操作---------");

        ArticleMemento memento = draftsBox.getMemento();
        editor.undoFromMemento(memento);
        System.out.println("--------第一次撤销,之后,信息如下:---------");
        System.out.println(editor);

        ArticleMemento memento2 = draftsBox.getMemento();
        editor.undoFromMemento(memento2);
        System.out.println("--------第二次撤销,之后,信息如下:---------");
        System.out.println(editor);

    }

}

测试截图 

备忘录模式的特点

优点

  1. 提供了对象状态的存储与恢复机制:备忘录模式可以将对象的内部状态保存在备忘录中,当需要时能够比较方便地将数据恢复到某个历史的状态。
  2. 实现了内部状态的封装:除了创建它的发起人之外,其他对象都不能够访问这些状态信息。
  3. 支持多次撤销和恢复操作:备忘录模式可以保存多个状态快照,使得客户端可以根据需求选择恢复到某个特定的状态。

缺点

  1. 资源消耗大:如果要保存的内部状态信息过多或者特别频繁,将会占用比较大的内存资源。
  2. 对象状态的存储和恢复需要时间和计算资源:备忘录模式需要对对象状态进行序列化和反序列化操作,可能需要消耗一定的时间和计算资源。

使用场景

  1. 需要在不破坏对象封装性的前提下保存和恢复对象的状态。
  2. 需要实现多级撤销和恢复操作。
  3. 需要保存对象历史状态以供分析和审计。

注意事项

  1. 注意备忘录对象的生命周期管理,避免资源泄露和内存溢出。
  2. 确保备忘录对象只被相关的原发器对象访问,避免违反封装原则。
  3. 为了节约内存,可使用原型模式+备忘录模式。

实际应用

  1. 文本编辑器:可以使用备忘录模式来实现文本编辑器的撤销和恢复功能,将文本的不同版本保存在备忘录中。
  2. 游戏进度保存与加载:游戏中可以使用备忘录模式来保存和加载游戏的进度,使得玩家可以随时恢复到之前的某个状态。
  3. 软件撤销和恢复功能:一些软件工具或者编辑器可以使用备忘录模式来实现撤销和恢复功能,保存用户对文件的修改历史。

更多消息资讯,请访问昂焱数据(https://www.ayshuju.com)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/839493.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ant.design 组件库中的 Tree 组件实现可搜索的树: React+and+ts

ant.design 组件库中的 Tree 组件实现可搜索的树&#xff0c;在这里我会详细介绍每个方法&#xff0c;以及容易踩坑的点。 效果图&#xff1a; 首先是要导入的文件 // React 自带的属性 import React, { useMemo, useState } from react; // antd 组件库中的&#xff0c;输入…

VSCode插件Todo Tree的使用

在VSCode中安装插件Todo Tree。按下快捷键ctrlshiftP&#xff0c;输入setting.jspn&#xff0c;选择相应的配置范围&#xff0c;我们选择的是用户配置 Open User Settings(JSON)&#xff0c;将以下代码插入其中。 //todo-tree 标签配置从这里开始 标签兼容大小写字母(很好的功…

JAVA方向的大数据包含啥内容?

文章目录 大数据是啥大数据就业方向知识体系HadoophiveHBaseSparkScala 总结 大数据是啥 你了解到的大数据是啥样子&#xff1f; 还是… 大数据(big data)&#xff0c;或称巨量资料&#xff0c;指的是所涉及的资料量规模巨大到无法透过主流软件工具&#xff0c;在合理时间…

麦肯锡战略思维四大原则

麦肯锡战略思维四大原则 曾任职麦肯锡、安永等国家国际知名咨询机构的周正元&#xff0c;在其著作《麦肯锡结构化战略思维》将其系统的整理呈现出来&#xff0c;便于学习和使用。 模型介绍 工作中的你&#xff0c;是不是经常遇到复杂问题&#xff0c;六神无主&#xff1f; 专业…

SpringBoot+SSM实战<一>:打造高效便捷的企业级Java外卖订购系统

文章目录 项目简介项目架构功能模块管理端用户端 技术选型用户层网关层应用层数据层工具 项目优缺点结语 黑马程序员最新Java项目实战《苍穹外卖》&#xff1a;让你轻松掌握SpringBootSSM的企业级开发技巧项目简介 《苍穹外卖》是一款为餐饮企业&#xff08;餐厅、饭店&#x…

PBR材质理解整理

PBR Material 草履虫都能看懂的PBR讲解&#xff08;迫真&#xff09; 先前看了很多遍类似的了&#xff0c;结合《Unity Shader 入门精要》中的内容整理了下便于以后理解&#xff0c;以后有补充再添加。 光与材质相交会发生散射和吸收&#xff0c;散射改变光的方向&#xff0c…

MySQL主从复制——概念、原理、搭建过程

文章目录 1.主从复制概念2.主从复制原理3.主从复制结构的搭建3.1 主库配置3.2 从库配置 4.测试主从复制是否搭建成功5.主从复制的小结 DML&#xff08;data manipulation language&#xff09;是数据操纵语言&#xff1a;它们是SELECT、UPDATE、INSERT、DELETE&#xff0c;就象…

LeetCode 热题 100 JavaScript--108. 将有序数组转换为二叉搜索树

给你一个整数数组 nums &#xff0c;其中元素已经按 升序 排列&#xff0c;请你将其转换为一棵 高度平衡 二叉搜索树。 高度平衡 二叉树是一棵满足「每个节点的左右两个子树的高度差的绝对值不超过 1 」的二叉树。 提示&#xff1a; 1 < nums.length < 104 -104 < n…

怎么维护好自己的电脑

你的电脑已经成为你工作、学习、娱乐的最佳工具之一&#xff0c;但是如果你不做好电脑维护工作&#xff0c;就可能面临着电脑变慢、蓝屏、崩溃等问题。在这篇文章中&#xff0c;我们将介绍10个电脑维护步骤&#xff0c;让你的电脑更加稳定&#xff01; 为什么需要电脑维护&…

【Kubernetes部署篇】基于Ubuntu20.04操作系统搭建K8S1.23版本集群

文章目录 一、集群架构规划信息二、系统初始化准备(所有节点同步操作)三、安装kubeadm(所有节点同步操作)四、初始化K8S集群(master节点操作)五、添加Node节点到K8S集群中六、安装Calico网络插件七、测试CoreDNS可用性 一、集群架构规划信息 pod网段&#xff1a;10.244.0.0/16…

我的创作纪念日-三周年

机缘 工作很长时间之后&#xff0c;才发现知识的根本&#xff0c;还是在于积累。俗话说好记性不如烂笔头。不管是特定产品相关的知识还是系统类的知识&#xff0c;又或者是语言类的知识&#xff0c;都有很多知识点需要积累。有了积累之后&#xff0c;工作起来才游刃有余。 原来…

掌握Memory Profiler技巧:识别内存问题

关于作者&#xff1a;CSDN内容合伙人、技术专家&#xff0c; 从零开始做日活千万级APP。 专注于分享各领域原创系列文章 &#xff0c;擅长java后端、移动开发、人工智能等&#xff0c;希望大家多多支持。 目录 一、导读二、概览三、如何使用四、页面说明4.1 Java 和 Kotlin 分配…

snap xxx has “install-snap“ change in progress

error description * 系重复安装&#xff0c;进程冲突 solution 展示snap的改变 然后sudo snap abort 22即可终止该进程 之后重新运行install command&#xff5e;&#xff5e; PS: ubuntu有时候加载不出来&#xff0c;执行resolvectl flush-caches&#xff0c;清除dns缓存…

Red Hat 安装JDK与IntelliJ IDEA

目录 前言 Red Hat 安装 JDK 1、更新软件包列表 2、安装OpenJDK 3、验证安装 Red Hat 安装IntelliJ IDEA 1、下载 IntelliJ IDEA 2、解压缩 IntelliJ IDEA 安装包 3、移动 IntelliJ IDEA 到安装目录 4、启动 IntelliJ IDEA 前言 YUM是基于Red Hat的Linux发行版的一个…

3.PyCharm安装

PyCharm是由JetBrains推出的Python开发IDE,是最受欢迎的Python IDE之一。PyCharm为Python开发者提供了许多高级功能如代码自动完成、调试等。它使用智能引擎来分析代码,能够自动识别代码中的错误并提供快速修复方案。PyCharm适用于各种规模的项目,包括小型Python脚本和大型P…

PHP8的程序结构-PHP8知识详解

在做任何事情之前&#xff0c;都需要遵循一定的规则。在PHP8中&#xff0c;程序能够安照人们的意愿执行程序&#xff0c;主要依靠程序的流程控制语句。 不管多复杂的程序&#xff0c;都是由这些基本的语句组成的。语句是构造程序的基本单位。程序执行的过程就是执行程序语句的…

【C++】类和对象 - 下

目录 1. 再谈构造函数1.1 构造函数体赋值1.2 初始化列表1.3 explicit关键字 2. static成员2.1 概念2.2 特性 3. 友元3.1 友元函数3.2 友元类 4. 内部类5. 匿名对象6. 拷贝对象时的一些编译器优化 1. 再谈构造函数 1.1 构造函数体赋值 在创建对象时&#xff0c;编译器通过调用…

【供电并接电路】2021-12-31

缘由在实际应用中mos管的导通问题 - 电路设计论坛 - 电子技术论坛 - 广受欢迎的专业电子论坛!MOS管实际应用中的开通问题-硬件开发-CSDN问答 设计的思想是&#xff0c;当CH_5.2V有5.2V电压时&#xff0c;Q7导通&#xff0c;Q6产生UGS​压差&#xff0c;从而使Q6导通&#xff0c…

在校外连接校内实验室服务器

zerotier 内网穿透 一、zerotier的操作 去官网注册、登录、创建网络 zerotier官网 我使用微软账号登录的&#xff0c;这个随便 点 Create A Network NETWORK ID点ID进去 二、服务器(校内)上的操作 1. Ubuntu配置SSH 如果出现不在sudoers列表的问题查看这里 sudo apt …

element-ui树形表格,左边勾选,右边显示选中的数据-功能(如动图)

功能如图 功能需求 表格树形表格勾选数据&#xff0c;右边显示对应勾选的数据内容&#xff0c;选中客户&#xff0c;自动勾选所有的店铺(子级)&#xff0c;选中其中一个店铺&#xff0c;自动勾选上客户(父级)&#xff0c;同时会存在只有客户&#xff08;下面没有子级的情况&am…