行为设计模式之Memento(备忘录)

行为设计模式之Memento(备忘录)

前言:
备忘录设计模式,有点像vmware快照可以回滚,idea的提交记录同样可以混滚,流程引擎中流程可以撤销到或者回滚到某个指定的状态。

1)意图

在不破坏封装性的前提下捕获一个对象的内部状态,并在对象之外保存这个状态。这样以后就可以将对象恢复到原先保存的状态。

2)结构

在这里插入图片描述

3)适用性

Mement 模式适用于:

  • 必须保存一个对象在某一个时刻的(部分)状态,这样以后需要时它才能恢复到先前的状态。
  • 如果一个用接口来让其他对象直接得到这些状态,将会暴露对象的实现细节并破坏对象的封装性。
import java.util.ArrayList;
import java.util.List;/*** @author psd 行为设计模式之备忘录模式*/
public class MementoPatternDemo {public static void main(String[] args) {// 创建管理者Caretaker caretaker = new Caretaker();//  创建原发器Originator originator = new Originator();originator.setState("state1");Memento back1 = originator.createMemento();caretaker.addMemento(back1);originator.setState("state2");Memento back2 = originator.createMemento();caretaker.addMemento(back2);originator.setState("state3");Memento back3 = originator.createMemento();caretaker.addMemento(back3);caretaker.showMemento();System.out.println("--------------------");Memento memento = caretaker.getMemento(2);originator.setState(memento.getState());System.out.println("回滚到第二次备份,还原之后的状态:" + originator.getState());}
}/*** 原发器*/
class Originator{private String state;public void setState(String state) {this.state = state;}public String getState() {return state;}public Memento createMemento(){return new Memento(state);}public void setMemento(Memento memento){this.state = memento.getState();}
}/*** 管理者*/
class Caretaker{private List<Memento> mementoList = new ArrayList<>();public void addMemento(Memento memento){mementoList.add(memento);}public Memento getMemento(int index){if (index >= 0 && index < mementoList.size()){return mementoList.get(index - 1);}return null;}public void showMemento(){int currentIndex = 1;for (Memento memento : mementoList) {System.out.println("第" + currentIndex + "个备忘录的状态为:" + memento.getState());currentIndex++;}}}/*** 备忘录*/
class Memento{private String state;public String getState() {return state;}public void setState(String state) {this.state = state;}public Memento(String state) {this.state = state;}
}

总结:

**备忘录模式(Memento Pattern)**的核心思想是在不破坏对象封装性的前提下,捕获并外部化(存储)一个对象的内部状态,以便以后可以将该对象恢复到原先保存的状态。

它的主要使用场景围绕着需要保存对象状态并在未来某个时刻恢复该状态的需求,同时要求不能直接暴露对象的内部实现细节(封装性原则)。以下是其最典型和常见的应用场景:

撤销/重做操作:

这是最经典的应用场景。 在文本编辑器、图形编辑器、IDE、电子表格、绘图软件等交互式应用中,用户需要能够撤销(Undo)之前的操作,并可能重做(Redo)被撤销的操作。

如何应用: 在执行任何会改变应用状态(如添加文字、移动图形、修改单元格值)的命令之前,创建该状态关键部分的备忘录(Memento)并保存到历史栈中。当用户执行“撤销”操作时,从栈顶弹出最近的备忘录,并用它恢复应用的状态。“重做”则通常使用另一个栈来存储被撤销的操作状态。

游戏存档/读档:

游戏中需要保存玩家的进度(角色位置、生命值、装备、关卡状态等),以便玩家下次可以继续游戏,或者在游戏失败后从检查点(Checkpoint)重新开始。

如何应用: 在玩家手动存档或到达检查点时,创建代表当前游戏状态(由游戏引擎或特定对象管理)的备忘录,并将其序列化存储到文件或数据库中。当玩家选择“加载游戏”时,读取相应的备忘录数据并反序列化,然后用它来恢复游戏引擎的状态。

事务回滚:

在数据库操作或需要原子性的业务流程中,如果一系列操作中的某一步失败,需要将所有操作回滚到事务开始前的状态,以保证数据一致性。

如何应用: 在事务开始时,为参与事务的关键业务对象创建备忘录。如果在事务过程中发生错误,则使用这些备忘录将所有对象恢复到事务开始前的状态。备忘录模式在这里更侧重于内存中业务对象的状态恢复,而数据库本身通常有自己的事务机制(如日志),但原理相通。

状态快照与恢复:

任何需要临时保存对象状态并在之后某个时刻精确恢复到该状态的场景。例如:

算法执行过程中可能需要回溯到之前的某个状态。

在复杂的配置工具中,允许用户保存当前的配置组合作为“快照”,之后可以一键恢复到这个快照配置。

工作流引擎中,保存流程实例在某个节点的状态,以便稍后(如系统重启后)从中断点继续执行。

需要临时修改对象状态进行某些操作,操作完成后需要还原到原始状态。

协作工具中的版本控制(基础原理):

虽然成熟的版本控制系统(如Git)复杂得多,但其核心思想之一也包含了备忘录模式的概念:保存文件或项目在某个时间点的完整状态(快照),允许用户回退到历史版本。备忘录模式为这种“保存状态-恢复状态”的能力提供了基础设计思路。

备忘录模式适用的关键判断点:

需要保存状态: 应用有明确的需求要在某个时间点记录对象的内部状态。

需要恢复状态: 应用有明确的需求要在未来某个时间点将对象恢复到之前保存的状态。

需要保持封装性: 直接暴露对象的所有内部字段来保存状态会破坏对象的封装性,带来维护困难和潜在的错误。备忘录模式通过一个只由原发器(Originator)对象操作的“备忘录”对象来间接存储状态,避免了其他对象直接访问其内部细节。

状态数据量可控: 虽然备忘录可以存储复杂状态,但频繁保存大量状态(如高分辨率图像编辑的每一步)可能导致内存消耗过大。这时可能需要结合增量存储、命令模式存储操作而非全状态、或外部存储(如数据库/文件)等策略进行优化。

总结来说,当你的应用需要实现“时光机”功能(如撤销、存档/读档、回滚、快照恢复),并且你希望以符合面向对象设计原则(特别是封装性)的方式来实现时,备忘录模式就是一个非常合适的选择。 它清晰地分离了状态捕获/恢复的职责(由Originator和Memento负责)和状态历史的存储管理职责(由Caretaker负责)。

喜欢我的文章记得点个在看,或者点赞,持续更新中ing…

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

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

相关文章

动画直播如何颠覆传统?解析足球篮球赛事的数据可视化革命

在5G和AI技术快速发展的今天&#xff0c;体育赛事直播正在经历一场深刻的变革。传统视频直播虽然能提供真实的比赛画面&#xff0c;但在战术可视化、数据深度和交互体验方面存在明显短板。而基于实时数据驱动的动画直播技术&#xff0c;正通过创新的方式弥补这些不足&#xff0…

二刷苍穹外卖 day01

nginx nginx反向代理 将前端发送的请求由nginx转发到后端服务器 好处&#xff1a; 提速&#xff1a;nginx本身可缓存数据 负载均衡&#xff1a;配置多台服务器&#xff0c;大量请求来临可均衡分配 保证后端安全&#xff1a;不暴露后端服务真实地址 server{listen 80;server_…

5.2 HarmonyOS NEXT应用性能诊断与优化:工具链、启动速度与功耗管理实战

HarmonyOS NEXT应用性能诊断与优化&#xff1a;工具链、启动速度与功耗管理实战 在HarmonyOS NEXT的全场景生态中&#xff0c;应用性能直接影响用户体验。通过专业的性能分析工具链、针对性的启动速度优化&#xff0c;以及精细化的功耗管理&#xff0c;开发者能够构建"秒…

模型训练-关于token【低概率token, 高熵token】

Qwen团队新发现&#xff1a;大模型推理能力的提高仅由少数高熵 Token 贡献 不要让低概率token主导了LLM的强化学习过程 一 低概率词元问题 论文&#xff1a;Do Not Let Low-Probability Tokens Over-Dominate in RL for LLMs 在RL训练过程中&#xff0c;低概率词元&#xff08…

XCTF-web-easyupload

试了试php&#xff0c;php7&#xff0c;pht&#xff0c;phtml等&#xff0c;都没有用 尝试.user.ini 抓包修改将.user.ini修改为jpg图片 在上传一个123.jpg 用蚁剑连接&#xff0c;得到flag

gRPC、WebSocket 与 HTTP 的核心区别对比

gRPC、WebSocket 与 HTTP 的核心区别对比&#xff0c;涵盖通信模式、协议特性及适用场景&#xff1a; &#x1f504; ‌一、通信模式‌ ‌HTTP‌ ‌单向请求-响应‌&#xff1a;客户端发起请求&#xff0c;服务器返回响应后连接立即关闭13。‌无状态协议‌&#xff1a;每次请求…

Android第十三次面试总结(四大 组件基础)

Activity生命周期和四大启动模式详解 一、Activity 生命周期 Activity 的生命周期由一系列回调方法组成&#xff0c;用于管理其创建、可见性、焦点和销毁过程。以下是核心方法及其调用时机&#xff1a; ​onCreate()​​ ​调用时机​&#xff1a;Activity 首次创建时调用。​…

讲讲JVM的垃圾回收机制

垃圾回收就是对内存堆中已经死亡或者长时间没有使用的对象进行清楚或回收。 JVM 在做 GC 之前&#xff0c;会先搞清楚什么是垃圾&#xff0c;什么不是垃圾&#xff0c;通常会通过可达性分析算法来判断对象是否存活。 在确定了那些垃圾可以被回收后&#xff0c;垃圾回收器&…

QT软件外包开发费用

国内QT软件外包开发费用是一个非常复杂的问题&#xff0c;没有一个固定的价格&#xff0c;它受到多种因素的影响。以下将详细阐述影响QT软件外包开发费用的主要因素&#xff0c;并提供大致的价格区间供参考&#xff08;请注意&#xff0c;这些价格仅为估算&#xff0c;实际报价…

iOS 16 SwiftUI 优雅跳转实践:用枚举路由和 NavigationStack 实现多页面导航

引言&#xff1a;跳转的混乱与优雅的必要性 SwiftUI 给我们带来了声明式界面的全新开发体验&#xff0c;但当涉及到页面跳转时&#xff0c;许多开发者仍然面临一些“旧痛”。最初的 NavigationLink(destination:isActive:) 或 sheet(isPresented:) 等方式虽然能用&#xff0c;…

TikTok矩阵养号实战:住宅IP纯净度与设备指纹联动方案

在TikTok矩阵运营中&#xff0c;住宅IP纯净度和设备指纹管理是规避风控的核心。以下方案整合多平台风控逻辑与实战数据&#xff0c;覆盖环境隔离、行为模拟到风险防控全流程。 &#x1f527; 一、住宅IP纯净度维持策略 IP筛选与验证 静态住宅IP优选&#xff1a;核心账号绑定目标…

Elasticsearch增删改查语句

创建索引库&#xff1a;不带映射的 PUT /索引名称 {"settings": {"number_of_shards": 3, // 主分片数"number_of_replicas": 1 // 每个主分片的副本数} } 创建带映射的索引库&#xff1a; PUT /products {"settings": {"…

树莓派4B, ubuntu20.04, 安装Ros Noetic[踩坑记录]

一、安装过程 1. 硬件要求 树莓派4B (建议4GB或8GB内存版本) 至少16GB的microSD卡 2. 下载并安装Ubuntu 20.04 Ubuntu 20.04 LTS (Focal Fossa) for Raspberry Pi 使用Raspberry Pi Imager或BalenaEtcher将镜像写入microSD卡 3. 安装ROS Noetic ​# 设置sources.list s…

视觉slam--框架

视觉里程计的框架 传感器 VO--front end VO的缺点 后端--back end 后端对什么数据进行优化 利用什么数据进行优化的 后端是怎么进行优化的 回环检测 建图 建图是指构建地图的过程。 构建的地图是点云地图还是什么信息的地图&#xff1f; 建图并没有一个固定的形式和算法…

每日算法 -【Swift 算法】删除链表的倒数第 N 个结点

🧩 Swift | 删除链表的倒数第 N 个结点(含详细注释) 在刷算法题时,我们经常会遇到关于链表的题目,而「删除链表的倒数第 N 个节点」是其中一个非常经典的题。今天我们就用 Swift 来实现它,并梳理清楚整个思路。 🧠 一、题目描述 给你一个链表,删除链表的倒数第 n 个…

Truffle 和 Ganache 使用指南

Truffle 和 Ganache 使用指南 Truffle 命令详解 Truffle 是一个流行的以太坊开发框架,提供了许多有用的命令来简化智能合约的开发、测试和部署。 常用 Truffle 命令 初始化项目 truffle init 创建一个新的 Truffle 项目结构。 编译合约 truffle compile 编译项目中的 Solid…

docker进阶之架构

一、OCI 名为OCI&#xff0c;全称 Open Container Initiative/开放容器倡议,其目的主要是为了制定容器技术的通用技术标准。目前主要有两种标准&#xff1a; 1、容器运行时标准 &#xff08;runtime spec&#xff09; 2、容器镜像标准&#xff08;image spec&#xff09; …

企业产品网络安全日志6月10日-WAF资费消耗排查

发生了什么事&#xff1f; 上个的费用账单出来了&#xff0c;WAF费用有点飙升。比平时多了50%到100%。 周五的时候就已经知道这个事情了&#xff0c;但当时考虑肯定是拦截了一些恶意请求&#xff0c;所以。 反正也是上个月的事情了&#xff0c;所以周一过来复盘一下 数了下&a…

vue3+el-table 利用插槽自定义数据样式

<el-table-column label"匹配度" prop"baseMatchingLevel"><template #default"scope"><div :style"{ color: scope.row.baseMatchingLevel > 0.8 ? #00B578 : #FA5151 }">{{ scope.row.baseMatchingLevel }}&l…

[密码学实战]C语言使用SDF库构建国密算法RESTful服务(五)

[密码学实战]C语言使用SDF库构建国密算法RESTful服务(五) 引言 在现代信息安全领域,国密算法(SM系列算法)作为中国自主研发的密码算法标准,在金融、政务等领域得到广泛应用。本文将详细介绍如何使用C语言结合SDF(Security Device Function)库,构建一个提供国密算法服…