设计模式(行为型)-备忘录模式

news2025/3/21 3:18:31

目录

定义

类图

角色

角色详解

(一)发起人角色(Originator)​

(二)备忘录角色(Memento)​

(三)备忘录管理员角色(Caretaker)​

优缺点

优点​

缺点​

使用场景

可回滚的操作场景​

游戏存档场景​

需要监控的副本场景​


定义

        备忘录模式,英文名为 Memento Pattern,是 GoF(Gang of Four,即设计模式领域的四位大师:Erich Gamma、Richard Helm、Ralph Johnson 和 John Vlissides)提出的 23 种经典设计模式之一,属于行为型设计模式范畴。其核心定义为:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。如此一来,后续便能够将该对象恢复到先前保存的状态。​

        打个比方,我们在使用绘图软件时,可能会进行一系列的绘图操作,如绘制图形、填充颜色、调整线条粗细等。如果没有备忘录模式,一旦我们操作失误,比如不小心删除了重要图形或者对颜色填充不满意,可能就很难恢复到之前理想的状态。但有了备忘录模式,绘图软件就可以在每次关键操作前,将当前画布的状态(即对象的内部状态,包括绘制的图形、颜色设置、线条样式等)捕获并保存起来。当我们想要撤销操作时,软件就能从这些保存的状态中取出对应的状态,将画布恢复到之前的样子。

类图

角色

        备忘录模式的类图主要涉及三个核心角色,它们相互协作,共同实现了对象状态的保存与恢复功能。​

  • 发起人角色(Originator):这一角色在类图中处于核心地位,它就像是一个拥有自主记忆能力的个体。发起人角色负责记录当前时刻自身的内部状态,同时具备创建和恢复备忘录数据的关键能力。在代码实现层面,它通常会有一个方法用于创建备忘录,将自身当前的状态信息打包存储到备忘录对象中;另外还会有一个方法,当需要恢复状态时,从传入的备忘录对象中提取信息,恢复自身的状态。例如,在一个游戏角色类中,游戏角色就是发起人角色,它可以创建一个备忘录来记录自己当前的等级、生命值、装备等状态,也能够从一个已有的备忘录中读取这些信息,恢复到之前保存的状态。​

  • 备忘录管理员角色(Caretaker):可以把备忘录管理员角色看作是一个细心的图书管理员,它负责对备忘录进行管理,包括保存和提供备忘录。然而,它并不直接操作备忘录中的内容,仅仅起到一个中间协调和管理的作用。在类图中,它与备忘录角色和发起人角色都有一定的关联,它从发起人角色那里获取备忘录对象并妥善保存,当发起人角色需要恢复状态时,再将对应的备忘录对象提供给发起人角色。比如在游戏存档系统中,备忘录管理员角色可能会将游戏角色创建的备忘录(记录了游戏角色的各种状态)存储到硬盘的特定位置,当玩家需要读取存档恢复游戏角色状态时,它再从存储位置取出对应的备忘录提供给游戏角色(发起人角色)。

  • 备忘录角色(Memento):备忘录角色如同一个精心设计的容器,专门用于存储发起人角色的内部状态。为了确保封装性,它通常会对状态信息进行合理的封装,防止外部对象随意访问和修改。在类图中,备忘录角色与发起人角色紧密关联,发起人角色能够访问备忘录角色中存储的详细状态信息,而其他外部角色则只能看到备忘录角色提供的有限接口,无法直接窥探和篡改其中的状态数据。以绘图软件为例,备忘录角色可能会存储画布上所有图形的坐标、形状、颜色等详细信息,这些信息对于绘图软件的核心逻辑(发起人角色)来说是可访问的,以便在需要时进行状态恢复,但对于外部的普通用户操作接口来说,是不可见且不可随意修改的。​

角色详解

(一)发起人角色(Originator)​

  • 状态记录:发起人角色需要精确地记录自身当前时刻的内部状态。这要求它对自身的各个属性和状态有清晰的认知,并能够将这些信息以一种可存储的方式整理出来。例如,在一个财务记账系统中,记账本对象作为发起人角色,需要记录当前的账目余额、每一笔交易的明细(包括交易时间、金额、对方账户等)等内部状态信息。​

  • 备忘录创建:发起人角色拥有创建备忘录的能力,它将当前记录好的内部状态信息封装到一个备忘录对象中。这个过程就像是把一本书的所有内容整理好后放进一个文件袋里。在代码实现上,通常会创建一个备忘录类的实例,并将自身的状态信息赋值给备忘录类的相应属性。比如,在一个文本编辑器中,文本对象作为发起人角色,当需要创建备忘录时,它会将当前文本的内容、光标位置、字体设置等信息封装到一个备忘录对象中。​

  • 状态恢复:当需要恢复到之前保存的状态时,发起人角色能够从传入的备忘录对象中提取相应的状态信息,并将自身的状态恢复到备忘录所记录的状态。这就如同从文件袋中取出书,重新阅读并按照书中记录的内容调整自身状态。例如,在一个图形设计软件中,图形对象作为发起人角色,当接收到一个包含之前图形状态信息的备忘录对象时,它会读取备忘录中的图形形状、颜色、位置等信息,将自身的图形状态恢复到对应的样子。​

(二)备忘录角色(Memento)​

  • 状态存储:备忘录角色的主要职责就是安全、可靠地存储发起人角色的内部状态。它会根据发起人角色的状态信息结构,设计相应的属性来存储这些信息。例如,在一个游戏角色的备忘录中,会有属性来存储角色的等级、生命值、魔法值、背包物品清单等信息。这些属性通常会被设置为私有的,以保证状态信息的封装性,防止外部非法访问和修改。​

  • 访问控制:为了维护封装性,备忘录角色会对状态信息的访问进行严格控制。对于发起人角色,它提供足够的接口,使得发起人能够读取和设置状态信息,以便进行状态恢复操作。但对于其他外部角色,只提供非常有限的接口,甚至不提供任何接口,避免外部对象随意获取和篡改备忘录中的状态信息。比如,在一个数据库事务的备忘录中,只有数据库事务处理模块(发起人角色)能够直接访问备忘录中记录的事务状态、数据修改内容等信息,而其他无关的业务模块则无法直接访问这些敏感信息。​

(三)备忘录管理员角色(Caretaker)​

  • 备忘录保存:备忘录管理员角色负责接收发起人角色创建的备忘录对象,并将其妥善保存起来。保存的方式可以有多种,比如存储在内存中的数据结构里(如列表、栈等),或者存储到外部存储设备(如硬盘、数据库)中。在一个文档编辑软件中,当用户进行保存操作时,文档对象(发起人角色)创建一个备忘录记录当前文档的状态,备忘录管理员角色则将这个备忘录存储到硬盘上的特定文档版本管理目录中。​

  • 备忘录提供:当发起人角色需要恢复状态时,备忘录管理员角色能够准确地找到并提供相应的备忘录对象给发起人角色。这就要求备忘录管理员角色在保存备忘录时,有合理的索引和管理机制,以便能够快速定位到需要的备忘录。例如,在一个版本控制系统中,备忘录管理员角色会根据版本号等信息,将对应的备忘录提供给需要恢复到特定版本状态的文件对象(发起人角色)。

优缺点

优点​

  • 状态恢复机制:备忘录模式为用户提供了一种极为便捷的状态恢复机制。在许多应用场景中,用户可能会因为误操作或者想要尝试不同的操作路径,而需要回到之前的某个状态。例如在文档编辑过程中,用户可能不小心删除了重要段落,通过备忘录模式实现的撤销功能,就可以轻松恢复到删除前的状态;在图形设计中,对某个图形的操作不满意,也能利用备忘录模式回到操作前的状态。这种状态恢复机制极大地提高了用户体验,减少了用户因为错误操作而产生的焦虑和时间浪费。​

  • 信息封装性:通过将对象的内部状态封装在备忘录对象中,备忘录模式实现了良好的信息封装。外部对象无法直接访问和修改发起人对象的内部状态,只有发起人对象自身能够通过备忘录对象来管理和恢复自己的状态。这不仅提高了系统的安全性,防止了外部非法操作对对象内部状态的破坏,还使得系统的结构更加清晰,各模块之间的耦合度降低。例如,在一个企业资源规划(ERP)系统中,财务模块的内部状态(如账目余额、成本核算数据等)通过备忘录模式进行封装,其他业务模块无法直接访问和修改这些敏感信息,保证了财务数据的准确性和安全性。​

  • 简化发起人类:备忘录模式减轻了发起人类的负担,使其不再需要自行管理和保存自身内部状态的多个版本。在没有使用备忘录模式时,发起人类可能需要维护复杂的数据结构来记录自身的状态变化历史,这会增加代码的复杂性和维护成本。而采用备忘录模式后,发起人只需要专注于自身的核心业务逻辑,状态的保存和管理工作由备忘录角色和备忘录管理员角色来完成。比如,在一个游戏角色类中,原本可能需要在游戏角色类内部维护一个复杂的状态栈来记录每次升级、战斗后的状态变化,使用备忘录模式后,游戏角色类只需要在需要时创建和恢复备忘录,状态的存储和管理工作交给了备忘录和备忘录管理员。​

缺点​

  • 资源消耗问题:如果发起人角色的状态数据量较大,并且需要频繁地创建和保存备忘录,那么在资源消耗方面会面临较大压力。每个备忘录对象都需要占用一定的内存空间,如果长时间积累大量的备忘录,可能会导致内存不足等问题。例如,在一个大型 3D 建模软件中,模型对象的状态(包括复杂的几何形状、材质纹理、光照设置等)数据量巨大,每保存一次状态就会生成一个庞大的备忘录对象,如果用户频繁进行保存操作,会迅速消耗大量的内存资源。​

  • 存储容量不确定性:备忘录管理员角色在保存备忘录时,往往难以预先知道一个备忘录对象会占用多大的存储空间。这就可能导致在存储管理方面出现问题,比如在有限的硬盘空间中,可能因为不断保存备忘录而导致空间不足,但又无法提前提醒用户某个操作会产生较大的存储开销。例如,在一个手机游戏中,游戏存档(即备忘录)的大小可能会因为玩家在游戏中的不同行为(如收集大量物品、解锁复杂剧情等)而有很大差异,游戏开发者很难准确预估每个存档的大小,这可能会给玩家带来存储空间不足的困扰。​

  • 状态有效性问题:当发起人角色的状态发生改变时,新的状态并不一定总是有效的。在这种情况下,如果频繁使用备忘录模式进行状态恢复,可能会导致系统陷入一种混乱的状态。而且,如果状态改变的成功率较低,频繁地保存和恢复备忘录可能并不是一个高效的解决方案,不如采用其他更合适的设计模式,如 “假如” 协议模式(在执行操作前先假设操作成功,进行一系列模拟操作,若实际操作失败再进行回滚等处理)。例如,在一个金融交易系统中,每一笔交易操作都可能改变账户的状态,但交易过程中可能会因为各种原因(如网络故障、账户余额不足等)导致交易失败,如果频繁使用备忘录模式来恢复交易前的账户状态,可能会影响系统的稳定性和交易效率。

使用场景

可回滚的操作场景​

  • 文本编辑软件:像我们日常使用的 Word、WPS 等文本编辑软件,其中的撤销(Ctrl + Z)和重做(Ctrl + Y)功能就是备忘录模式的典型应用。在我们输入文字、修改格式、删除内容等操作过程中,文本编辑软件会在每次关键操作前创建一个备忘录,记录当前文档的状态。当我们按下撤销键时,软件就从之前保存的备忘录中取出对应的状态,将文档恢复到上一个操作前的状态;按下重做键时,则从后续保存的备忘录中获取状态,将文档恢复到撤销前的状态。​

游戏存档场景​

  • 游戏存档是备忘录模式最为人熟知的应用场景之一。在各种类型的游戏中,玩家在游戏过程中会不断改变游戏角色的状态(如等级提升、装备获取、任务进度推进等)。为了让玩家能够在后续继续游戏时从之前保存的进度开始,游戏系统会在玩家进行存档操作时,创建一个备忘录记录游戏角色的当前状态,包括角色的各项属性(生命值、魔法值、攻击力等)、背包中的物品、所处的游戏地图位置、完成的任务列表等信息。当玩家读取存档时,游戏系统从对应的备忘录中获取这些信息,将游戏角色恢复到存档时的状态,让玩家能够继续之前的游戏体验。例如,在一款大型角色扮演游戏中,玩家经过长时间的探索和战斗,到达了一个关键的游戏场景,此时玩家选择存档。之后,当玩家再次打开游戏读取存档时,游戏角色会以存档时的状态出现在之前的游戏场景中,玩家可以继续后续的游戏冒险。​

  • 综上所述,备忘录模式在软件开发的众多领域中都有着广泛而重要的应用,它为我们提供了一种强大的状态管理和恢复机制,虽然存在一些缺点,但在合适的场景下合理运用,能够显著提升系统的质量和用户体验。在实际的软件设计和开发过程中,我们需要根据具体的业务需求和系统特点,权衡利弊,决定是否采用备忘录模式来解决状态管理相关的问题。

  • 系统配置管理:在大型企业级系统中,系统配置的正确性对于系统的稳定运行至关重要。为了防止因为错误的配置修改导致系统故障,系统配置管理模块可以采用备忘录模式。在每次对系统配置进行修改前,创建一个备忘录记录当前的配置状态。如果修改后的配置导致系统出现问题,就可以从备忘录中恢复到之前正确的配置状态。比如,在一个云计算平台中,对服务器的网络配置、资源分配策略等进行修改时,利用备忘录模式可以保证在出现问题时能够快速回滚到稳定的配置状态。​

需要监控的副本场景​

  • 数据库事务管理:数据库事务是指作为单个逻辑工作单元执行的一系列操作,这些操作要么全部成功,要么全部失败。在数据库事务处理中,备忘录模式被广泛应用于事务的回滚操作。当开始一个事务时,数据库系统会创建一个备忘录,记录事务开始前数据库的状态(包括数据的版本、锁的状态等)。如果在事务执行过程中出现错误,系统就可以根据备忘录中的信息将数据库恢复到事务开始前的状态,保证数据的一致性和完整性。例如,在一个银行转账事务中,当从一个账户扣除金额并向另一个账户添加金额的过程中,如果出现网络故障等问题,就可以利用备忘录模式回滚事务,确保两个账户的金额不会出现错误的变动。​

  • 命令行操作:在操作系统的命令行界面中,有时我们可能会连续执行多个命令,当发现某个命令执行错误时,希望能够回滚到之前的系统状态。一些先进的命令行工具就采用了备忘录模式,记录每次命令执行前系统的关键状态(如文件系统状态、环境变量等),当用户执行撤销命令时,能够恢复到之前正确的状态。​

  • 图形设计软件:在 Adobe Photoshop、Sketch 等图形设计软件中,用户对图形的绘制、变形、颜色调整等操作都可以通过备忘录模式实现可回滚。比如,当我们对一个图层进行了复杂的滤镜处理后,发现效果不理想,就可以利用备忘录模式撤销滤镜操作,恢复图层原来的状态。这种可回滚操作极大地提高了图形设计的灵活性和创作效率,让设计师能够更加大胆地尝试各种设计思路。​

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

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

相关文章

Advanced Intelligent Systems 软体机器手助力截肢者玩转鼠标

随着科技的不断进步,假肢技术在改善截肢者生活质量方面取得了显著成就。然而,截肢群体在就业方面仍面临巨大困难,适龄截肢群体的就业率仅为健全群体的一半。现有的肌电控制假肢手在与计算机交互时存在诸多挑战,特别是截肢者在使用…

每日Attention学习27——Patch-based Graph Reasoning

模块出处 [NC 25] [link] Graph-based context learning network for infrared small target detection 模块名称 Patch-based Graph Reasoning (PGR) 模块结构 模块特点 使用图结构更好的捕捉特征的全局上下文将图结构与特征切片(Patching)相结合,从而促进全局/…

深圳南柯电子|医疗设备EMC检测测试整改:保障患者安全的第一步

在医疗设备领域,电磁兼容性(EMC)是确保设备安全、有效运行的关键指标。随着医疗技术的飞速发展,医疗设备日益复杂,其电磁环境也愈发复杂多变。EMC检测测试及整改因此成为医疗设备研发、生产、销售过程中不可或缺的一环…

【笔记】计算机网络——数据链路层

概述 链路是从一个结点到相邻结点的物理路线,数据链路则是在链路的基础上增加了一些必要的硬件和软件实现 数据链路层位于物理层和网络层之间,它的核心任务是在直接相连的节点(如相邻的交换机,路由器)之间提供可靠且…

STM32-汇编

学习arm汇编的主要目的是为了编写arm启动代码,启动代码启动以后,引导程序到c语言环境下运行。换句话说启动代码的目的是为了在处理器复位以后搭建c语言最基本的需求。因此启动代码的主要任务有: 初始化异常向量表; 初始化各工作模…

利用通义灵码AI在VS Code中快速开发扫雷游戏:Qwen2.5-Max模型的应用实例

引言 随着人工智能技术的不断进步,开发过程中的自动化程度也在逐步提高。阿里云推出的通义灵码AI程序员,作为一款创新型的智能编程助手,现已全面上线并兼容VS Code、JetBrains IDEs等多种开发环境。本文将介绍如何利用最新的Qwen2.5-Max模型…

202503执行jmeter压测数据库(ScyllaDB,redis,lindorm,Mysql)

一、Mysql 1 、 准备MySQL 连接内容 2 、 下载连接jar包 准备 mysql-connector-java-5.1.49.jar 放到 D:\apache-jmeter-5.6.3\lib\ext 目录下面; 3 、 启动jmeter ,配置脚本 添加线程组---》JDBC Connection Configuration---》JDBC Request---》查看结果树。 1)测…

以太网 MAC 帧格式

文章目录 以太网 MAC 帧格式以太网帧间隔参考 本文为笔者学习以太网对网上资料归纳整理所做的笔记,文末均附有参考链接,如侵权,请联系删除。 以太网 MAC 帧格式 以太网技术的正式标准是 IEEE 802.3,它规定了以太网传输数据的帧结…

【PCB工艺】基础:电子元器件

电子原理图(Schematic Diagram)是电路设计的基础,理解电子元器件和集成电路(IC)的作用,是画好原理图的关键。 本专栏将系统讲解 电子元器件分类、常见 IC、电路设计技巧,帮助你快速掌握电子电路…

从WebRTC到嵌入式:EasyRTC如何借助大模型提升音视频通信体验

随着人工智能技术的快速发展,WebRTC与大模型的结合正在为音视频通信领域带来革命性的变革。WebRTC作为一种开源实时通信技术,以其低延迟、跨平台兼容性和强大的音视频处理能力,成为智能硬件和物联网设备的重要技术支撑。 而EasyRTC作为基于W…

前端样式库推广——TailwindCss

官方网址: https://tailwindcss.com/docs/installation/using-vite 中文官方文档:https://www.tailwindcss.cn/ github地址:tailwindcss 正在使用tailwindcss的网站:https://tailwindcss.com/showcase 一看github,竟然…

SpringBoot 第二课(Ⅰ) 整合springmvc(详解)

目录 一、SpringBoot对静态资源的映射规则 1. WebJars 资源访问 2. 静态资源访问 3. 欢迎页配置 二、SpringBoot整合springmvc 概述 Spring MVC组件的自动配置 中央转发器(DispatcherServlet) 控制器(Controller) 视图解…

OpenHarmony 开源鸿蒙北向开发——3.配置SDK

安装、配置完成之后我们就要配置SDK。 我们创建工程后,点击右上角设置 进入设置 进入OpenHarmony SDK,选择编辑 这里配置一下SDK安装位置 点击完成 这里我们API版本勾选第一个即可 确认安装 勾选接受 这里要等一会 安装完成后,点击完成

vulhub Matrix-Breakout

1.下载靶机,打开靶机和kali虚拟机 2.查询kali和靶机ip 3.浏览器访问 访问81端口有登陆界面 4.扫描敏感目录 kali dirb 扫描 一一访问 robot.txt提示我们继续找找,可能是因为我们的字典太小了,我们换个扫描器换个字典试下,利用kali自带的最大…

Unity3D开发AI桌面精灵/宠物系列 【二】 语音唤醒 ivw 的两种方式-Windows本地或第三方讯飞等

Unity3D 交互式AI桌面宠物开发系列【二】ivw 语音唤醒 该系列主要介绍怎么制作AI桌面宠物的流程,我会从项目开始创建初期到最终可以和AI宠物进行交互为止,项目已经开发完成,我会仔细梳理一下流程,分步讲解。 这篇文章主要讲有关于…

三月九次前端面试复盘:当场景题成为通关密钥

三月初集中面了包括字节、美团、滴滴在内的9家公司,经历7场技术面2场Leader面后,发现如今的面试逻辑已发生根本转变。这里分享真实经历与题目,供近期求职者参考。 一、面试形态变化:从理论背诵到实战推演 1. 八股文边缘化&#…

C++输入输出流第一弹:标准输入输出流 详解(带测试代码)

目录 C输入输出流 流的四种状态(重点) 标准输入输出流 标准输入流 逗号表达式 1. 逗号表达式的基本规则 示例 2. 图片中的代码分析 关键点解析 3. 常见误区 误区 1:逗号表达式等同于逻辑与 && 误区 2:忽略输入…

鸿蒙NEXT项目实战-百得知识库05

代码仓地址,大家记得点个star IbestKnowTeach: 百得知识库基于鸿蒙NEXT稳定版实现的一款企业级开发项目案例。 本案例涉及到多个鸿蒙相关技术知识点: 1、布局 2、配置文件 3、组件的封装和使用 4、路由的使用 5、请求响应拦截器的封装 6、位置服务 7、三…

黑马node.js教程(nodejs教程)——AJAX-Day01-04.案例_地区查询——查询某个省某个城市所有地区(代码示例)

文章目录 代码示例效果 代码示例 axiosTest.html <!DOCTYPE html> <!-- 文档类型声明&#xff0c;告诉浏览器这是一个HTML5文档 --> <html lang"en"> <!-- HTML根元素&#xff0c;设置文档语言为英语 --><head> <!-- 头部区域&am…

vue 自制列表,循环滚动

需求人员表示&#xff0c;超过高度的表格内容需要滚动展示&#xff0c;所以效果图如下&#xff1a; 自定义列表样式&#xff0c;主要是通过flex布局&#xff0c;控制 类th 与 类td 的宽度保持一致&#xff0c;标签结构还是参考了table的结构&#xff0c;由thead与tbody包裹tr再…