当前位置: 首页 > news >正文

【设计模式-备忘录】

备忘录模式(Memento Pattern)是一种行为型设计模式,用于保存对象的内部状态,以便在将来某个时间可以恢复到该状态,而不暴露对象的内部实现细节。备忘录模式特别适合在需要支持撤销(Undo)操作的应用中。

定义

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

UML图

在这里插入图片描述
备忘录模式涉及的角色:

  • Originator(发起者):负责创建备忘录对象,用来记录自己的内部状态,并可以根据备忘录恢复状态。
  • Memento(备忘录):存储发起者的内部状态,防止对象的内部状态泄露。通常只允许发起者访问其内部状态。
  • Caretaker(负责人):负责保存备忘录对象,但不能对备忘录的内容进行操作或访问。

代码

import java.util.ArrayList;
import java.util.List;// 发起者类
class Originator {private String state;// 设置状态public void setState(String state) {this.state = state;System.out.println("当前状态: " + state);}// 保存当前状态到备忘录public Memento saveStateToMemento() {return new Memento(state);}// 从备忘录中恢复状态public void getStateFromMemento(Memento memento) {state = memento.getState();System.out.println("恢复到状态: " + state);}// 备忘录类public static class Memento {private final String state;public Memento(String state) {this.state = state;}public String getState() {return state;}}
}// 负责人类
class Caretaker {private final List<Originator.Memento> mementoList = new ArrayList<>();// 添加备忘录public void add(Originator.Memento state) {mementoList.add(state);}// 获取备忘录public Originator.Memento get(int index) {return mementoList.get(index);}
}// 测试类
public class MementoPatternDemo {public static void main(String[] args) {Originator originator = new Originator();Caretaker caretaker = new Caretaker();// 保存状态originator.setState("状态1");caretaker.add(originator.saveStateToMemento());originator.setState("状态2");caretaker.add(originator.saveStateToMemento());originator.setState("状态3");caretaker.add(originator.saveStateToMemento());// 恢复状态originator.getStateFromMemento(caretaker.get(1)); // 恢复到状态2originator.getStateFromMemento(caretaker.get(0)); // 恢复到状态1}
}

场景

1. 撤销/恢复操作

在需要支持“撤销(Undo)”和“恢复(Redo)”的应用中,备忘录模式非常适用。每当状态发生变化时,可以保存一个备忘录对象,用户可以在需要时撤销操作,恢复到之前的状态。
应用场景:

  • 文本编辑器:例如,在文本处理软件中,用户进行编辑时,每次输入、删除或格式化操作都改变文档的状态。通过备忘录模式,用户可以撤销某些操作,并恢复到之前的编辑状态。
  • 绘图软件:绘图过程中每一步的修改都可能需要撤销或恢复。

2. 保存历史状态

当需要记录一个对象的历史状态,并在将来某一时刻恢复特定状态时,备忘录模式是一个合适的选择。这样可以在不破坏对象封装性的前提下保存状态。

应用场景:

  • 版本控制系统:在版本控制中,每次保存都会存储文件或项目的状态,以便之后能够回溯到某个特定版本。
  • 游戏进度保存:在游戏中,玩家的进度(如等级、位置、装备等)可以存储为备忘录对象,并在玩家需要时从存档中恢复游戏。

3. 事务管理

在涉及复杂事务处理的系统中,备忘录模式可以用于事务回滚,即当事务中的某些操作失败时,能够恢复到之前的状态。

应用场景:

  • 数据库事务管理:在处理数据库事务时,如果某一步操作出错,可以回滚到事务开始时的状态,从而保证数据一致性。
  • 金融交易系统:在处理复杂的金融交易时,如果发生异常,能够回滚到交易前的状态,避免数据异常。

4. 需要避免暴露对象细节

在某些情况下,系统可能需要恢复对象的状态,但不希望暴露对象的内部实现细节。备忘录模式可以在不破坏对象封装的情况下,保存和恢复对象状态。

应用场景:

  • 封装复杂对象:例如,某个对象的内部状态比较复杂,外部系统需要在多个状态之间切换,但是不希望外部直接访问对象的内部状态。备忘录模式允许外部保存和恢复状态,而不需要了解对象的内部实现。

5. 定时或阶段性保存

当系统需要阶段性地保存对象的状态,以防系统崩溃或其他意外情况时,备忘录模式可以记录当前的状态,确保系统可以在异常结束后恢复到安全状态。

应用场景:

  • 自动备份系统:例如,某个系统在特定时间或操作后定时保存数据,并在崩溃后自动恢复。

6. 数据快照

当系统需要保存某一时刻的状态快照,以便后续能够对比或恢复时,备忘录模式可以记录状态快照。

应用场景:

  • 调试与监控:开发人员可以在系统运行的不同阶段记录状态快照,并在调试过程中进行恢复以定位问题。

7. 复杂状态管理

对于那些有复杂状态管理需求的系统,备忘录模式可以帮助解决状态的存储与恢复问题,确保状态管理的灵活性。

应用场景:

  • 用户设置的恢复:在软件应用中,用户可能会进行复杂的设置操作,通过备忘录模式,系统可以允许用户将配置恢复到之前的某个设置。

局限性

尽管备忘录模式适用于上述场景,但它在某些情况下可能不是最优选择,特别是当:

  • 状态数据庞大:如果对象的状态信息较大,存储多个备忘录对象可能会占用大量内存。
  • 状态变更频繁:在频繁保存状态的情况下,备忘录的维护成本较高,可能会引发性能问题。

总结

备忘录模式的优点在于它在保持对象封装性、实现撤销功能、简化状态管理、降低耦合度的同时,支持系统的状态历史保存和事务处理回滚。它特别适用于需要保存和恢复对象状态的应用场景。

相关文章:

【设计模式-备忘录】

备忘录模式&#xff08;Memento Pattern&#xff09;是一种行为型设计模式&#xff0c;用于保存对象的内部状态&#xff0c;以便在将来某个时间可以恢复到该状态&#xff0c;而不暴露对象的内部实现细节。备忘录模式特别适合在需要支持撤销&#xff08;Undo&#xff09;操作的应…...

【数据结构】排序算法系列——快速排序(附源码+图解)

快速排序 接下来我们将要介绍的是排序中最为重要的算法之一——快速排序。 快速排序&#xff08;英语&#xff1a;Quicksort&#xff09;&#xff0c;又称分区交换排序&#xff08;partition-exchange sort&#xff09;&#xff0c;最早由东尼霍尔提出。快速排序通常明显比其…...

Arthas thread(查看当前JVM的线程堆栈信息)

文章目录 二、命令列表2.1 jvm相关命令2.1.2 thread&#xff08;查看当前JVM的线程堆栈信息&#xff09;举例1&#xff1a;展示[数字]线程的运行堆栈&#xff0c;命令&#xff1a;thread 线程ID举例2&#xff1a;找出当前阻塞其他线程的线程 二、命令列表 2.1 jvm相关命令 2.…...

Tomcat_WebApp

Tomcat的目录的介绍 /bin&#xff1a; 这个目录包含启动和关闭 Tomcat 的脚本。 startup.bat / startup.sh&#xff1a;用于启动 Tomcat&#xff08;.bat 文件是 Windows 系统用的&#xff0c;.sh 文件是 Linux/Unix 系统用的&#xff09;。shutdown.bat / shutdown.sh&#xf…...

代码随想录算法训练营Day10

150. 逆波兰表达式求值 力扣题目链接&#xff1b;. - 力扣&#xff08;LeetCode&#xff09; Collection——Deque——LInkedList类 class Solution {public int evalRPN(String[] tokens) {Deque<Integer> myquenew LinkedList<>();for(String a:tokens){if(a.…...

十个服务器中毒的常见特征及其检测方法

服务器作为企业的核心资源&#xff0c;其安全性至关重要。一旦服务器被病毒入侵&#xff0c;不仅会影响系统的正常运行&#xff0c;还可能导致数据泄露等严重后果。以下是十种常见的服务器中毒特征及其检测方法。 1. 系统性能下降 病毒常常占用大量的CPU和内存资源&#xff0…...

LeetCode 每周算法 6(图论、回溯)

LeetCode 每周算法 6&#xff08;图论、回溯&#xff09; 图论算法&#xff1a; class Solution: def dfs(self, grid: List[List[str]], r: int, c: int) -> None: """ 深度优先搜索函数&#xff0c;用于遍历并标记与当前位置(r, c)相连的所有陆地&…...

Selenium元素定位:深入探索与实践

目录 一、引言 二、Selenium元素定位基础 1. WebDriver与元素定位 2. 定位策略概览 三、ID定位 1. 特点与优势 2. 示例代码 四、Class Name定位 1. 特点与限制 2. 示例代码 五、XPath定位 1. 特点与优势 2. 示例代码 3. XPath高级用法 六、CSS Selector定位 1.…...

前端开发——(1)使用vercel进行网页开发

前端开发——&#xff08;1&#xff09;使用Vercel进行网页开发 在现代前端开发中&#xff0c;选择一个高效的部署平台至关重要。Vercel 提供了快速、简便的部署方式&#xff0c;特别适合静态网站和 Next.js 应用。本文将带你逐步了解如何使用 Vercel 部署并运行你的网页项目。…...

故障诊断│GWO-DBN灰狼算法优化深度置信网络故障诊断

1.引言 随着人工智能技术的快速发展&#xff0c;深度学习已经成为解决复杂问题的热门方法之一。深度置信网络&#xff08;DBN&#xff09;作为深度学习中应用比较广泛的一种算法&#xff0c;被广泛应用于分类和回归预测等问题中。然而&#xff0c;DBN的训练过程通常需要大量的…...

【工具】Windows|两款开源桌面窗口管理小工具Deskpins和WindowTop

总结 Deskpins 功能单一&#xff0c;拖到窗口上窗口就可以置顶并且标记钉子标签&#xff0c;大小 104 KB&#xff0c;开源位置&#xff1a;https://github.com/thewhitegrizzli/DeskPins/releases WindowTop 功能完善全面强大&#xff0c;包括透明度、置顶、选区置顶等一系列功…...

【Unity杂谈】iOS 18中文字体显示问题的调查

一、问题现象 最近苹果iOS 18系统正式版推送&#xff0c;周围升级系统的同事越来越多&#xff0c;有些同事发现&#xff0c;iOS 18上很多游戏&#xff08;尤其是海外游戏&#xff09;的中文版&#xff0c;显示的字很奇怪&#xff0c;就像一些字被“吞掉了”&#xff0c;无法显示…...

后端-navicat查找语句(单表与多表)

表格字段设置如图 语句&#xff1a; 1.输出 1.输出name和age列 SELECT name,age from student 1.2.全部输出 select * from student 2.where子语句 1.运算符&#xff1a; 等于 >大于 >大于等于 <小于 <小于等于 ! <>不等于 select * from stude…...

基于springboot的在线视频点播系统

文未可获取一份本项目的java源码和数据库参考。 国外研究现状&#xff1a; 与传统媒体不同的是&#xff0c;新媒体在理念和应用上都采用了新颖的媒介或媒体。新媒体是指应用在数字技术、在传统媒体基础上改造、或者更新换代而来的媒介或媒体。新兴媒体与传统媒体在理念和应用…...

笔记整理—内核!启动!—kernel部分(8)动态编译链接库与BSP文件

linux的C语言程序是用编译的&#xff0c;但是如果要在开发板上运行的话就不能使用默认的ubuntu提供的gcc编译器&#xff0c;而是使用arm-linux版本的一类的编译器。我们可以用file xx去查看一个程序的架构。 &#xff08;arm架构&#xff09; &#xff08;intel的80386架构&…...

Cpp类和对象(中续)(5)

文章目录 前言一、赋值运算符重载运算符重载赋值运算符重载赋值运算符不可重载为全局函数前置和后置的重载 二、const修饰成员函数三、取地址及const取地址操作符重载四、日期类的实现构造函数日期 天数日期 天数日期 - 天数日期 - 天数日期类的大小比较日期类 > 日期类日…...

深度学习02-pytorch-01-张量的创建

深度学习 pytorch 框架 是目前最热门的。 深度学习 pytorch 框架相当于 机器学习阶段的 numpy sklearn 它将数据封装成张量(Tensor)来进行处理&#xff0c;其实就是数组。也就是numpy 里面的 ndarray . pip install torch1.10.0 -i https://pypi.tuna.tsinghua.edu.cn/simp…...

pg入门9—pg中的extentions是什么

在 PostgreSQL&#xff08;PG&#xff09;中&#xff0c;Extension&#xff08;扩展&#xff09; 是一组预先打包的功能模块&#xff0c;可以轻松地添加到数据库中以扩展其功能。这些扩展通常包含新的数据类型、函数、索引方法、操作符以及其他数据库增强功能。通过扩展&#x…...

JAVA:Nginx(轻量级的Web服务器、反向代理服务器)--(1)

一、Nginx:起因 nginx为什么为开发出来,起因是什么 总述:NGINX 的开发起因源于上世纪 90 年代末至 2000 年代初的互联网快速发展。当时,互联网流量急剧增长,特别是像 Apache 这样的传统 Web 服务器在高并发连接处理方面开始显现出瓶颈。 举例子:Apache 的 "每个连接…...

互斥锁和自旋锁

1、锁&#xff1a; 自旋锁与‌互斥锁的区别主要体现在以下几个方面&#xff1a; 1. 实现方式 ‌互斥锁‌&#xff1a;属于‌sleep-waiting类型的锁。当一个线程尝试获取已被其他线程持有的互斥锁时&#xff0c;该线程会被阻塞&#xff08;进入睡眠状态&#xff09;&#xff…...

救生圈检测系统源码分享

救生圈检测检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Computer Visio…...

容器技术--Dockerfile 构建镜像

Dockerfile dockerfile 是一系列命令&参数构成的脚本,这些命令应用于基础镜像,最终创建一个新的镜像,可以提供一致的运行环境。【也可以登录容器,自己安装软件,最后commit为镜像】 命令 FROM 指定基础镜像(必须),如FROM ubuntu;每一个指令就生成一层镜像;RUN 运…...

Hive企业级调优[5]—— HQL语法优化之数据倾斜

目录 HQL语法优化之数据倾斜 数据倾斜概述 分组聚合导致的数据倾斜 优化说明 优化案例 Join导致的数据倾斜 优化说明 优化案例 HQL语法优化之数据倾斜 数据倾斜概述 数据倾斜问题通常指的是参与计算的数据分布不均&#xff0c;即某个key或某些key的数据量远超其他key&#xff…...

表示速度的speed与velocity语义辨析

speed 对应的中文是 速度, 比如 5KM/h, 但是语义中不带方向&#xff0c;所以一般用来表示标量(scalar)。velocity 对应的中文也是 速度, 比如 5KM/h, 语义中蕴含了方向&#xff0c; 常用于表示向量(vector)。 2024年09月22日...

Electron 图标修改

目录 1. 图片基本要求 2. 在main.js中配置icon 位置 ​3. 在package.json 中配置icon 位置 4. 问题&#xff1a;左上角图片 开发环境下显示&#xff0c;生产环境下不显示 1. 图片基本要求 图片格式为ico&#xff0c;图片像素像素为256*256&#xff1b; 将ico文件放在pub…...

项目扩展二:消息拉取功能的实现

项目扩展二&#xff1a;消息拉取功能的实现 一、回顾一下消息推送功能是如何实现的二、设计消息拉取功能1.服务器如何处理2.定义Request和Response1.定义Request2.proto文件 三、服务器实现消息拉取1.业务模块的实现&#xff1a;信道模块2.消费者管理模块实现O(1)获取消费者1.目…...

C语言6大常用标准库 -- 4.<math.h>

目录 引言 4. C标准库--math.h 4.1 简介 4.2 库变量 4.3 库宏 4.4 库函数 4.5 常用的数学常量 &#x1f308;你好呀&#xff01;我是 程序猿 &#x1f30c; 2024感谢你的陪伴与支持 ~ &#x1f680; 欢迎一起踏上探险之旅&#xff0c;挖掘无限可能&#xff0c;共同成长&…...

【图像匹配】基于SIFT算法的图像匹配,matlab实现

博主简介&#xff1a;matlab图像代码项目合作&#xff08;扣扣&#xff1a;3249726188&#xff09; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 本次案例是基于基于SIFT算法的图像匹配&#xff0c;用matlab实现。 一、案例背景和算法介绍 本…...

C++门迷宫

目录 开头程序程序的流程图程序游玩的效果下一篇博客要说的东西 开头 大家好&#xff0c;我叫这是我58。 程序 #include <iostream> using namespace std; void printmaze(const char strmaze[11][11]) {int i 0;int ia 0;for (; i < 11; i) {for (ia 0; ia <…...

用最通俗易懂的语言和例子讲解三维点云

前言&#xff1a; 我整体的学习顺序是看的按B站那“唯一”的三维点云的视频学习的&#xff08;翻了好久几乎没有第二个...&#xff09;对于深度学习部分&#xff0c;由于本人并没有进行学习&#xff0c;所以没有深究。大多数内容都进行了自己的理解并找了很多网络的资源方便理解…...