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

【设计模式深度剖析】【8】【行为型】【备忘录模式】| 以后悔药为例加深理解

👈️上一篇:观察者模式

设计模式-专栏👈️

---

文章目录

  • 备忘录模式
  • 定义
    • 英文原话
    • 直译
    • 如何理解呢?
  • 3个角色
    • 1. Memento(备忘录)
    • 2. Originator(原发器)
    • 3. Caretaker(负责人)
    • 类图
    • 代码示例
  • 备忘录模式的应用
    • 备忘录模式的优点
    • 备忘录模式的缺点
    • 备忘录模式的使用场景

备忘录模式

备忘录模式(Memento Pattern)又称为快照(Snapshot)模式或Token模式。

备忘录模式就像我们在生活中使用的“后悔药”。有时候,我们可能会做出一些决定或操作,但事后可能会后悔,希望回到之前的状态。备忘录模式就是这样一种“后悔药”,它能够帮助我们在需要的时候,返回到之前的状态。比如,在写文档时,如果我们不小心删除了一个重要的段落,使用备忘录模式,我们就可以轻松地恢复到删除之前的状态。但是,这种“后悔药”也有副作用,那就是它可能会占用一些资源,就像我们需要空间来保存这些后悔的机会一样。

定义

英文原话

Without violating encapsulation,capture and externalizean object’s internal state so that the object can be restored to this state later.

直译

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

如何理解呢?

有时有必要记录一个对象的内部状态。

为了允许用户取消不确定的操作或从错误中恢复过来,需要实现检查点和取消机制,而要实现这些机制,你必须事先将状态信息保存在某处,这样才能将对象恢复到他们先前的状态。

但是对象通常封装了其部分或所有的状态信息,使得其状态不能被其他对象访问,也就不可能在该对象之外保存其状态。

而暴露其内部状态又将违反封装的原则,可能有损应用的可靠性和可扩展性。

我们可以用备忘录(Memento)模式解决这一问题。

一个备忘录(memento)是一个对象,他存储另一个对象(原发器originator)在某个瞬间的内部状态,而后者称为备忘录的原发器originator)。

当需要设置原发器的检查点时,备份机制向原发器请求一个备忘录。

原发器用描述当前状态的信息初始化备忘录

只有原发器(originator)可以向备忘录中存取信息,备忘录对其他的对象不可见。

适用于必须保存一个对象在某一时刻的(部分)状态(以便以后有需要可以恢复回此状态)且如果用接口让其他对象直接得到这些状态,将会暴露对象实现细节并破坏对象的封装性。在这样的场景下使用备忘录(Memento)模式。

3个角色

1. Memento(备忘录)

负责存储Originator对象的内部状态,并可以防止Originator以外的其他对象访问备忘录。

备忘录有两个接口:Caretaker只能看到备忘录的窄接口,他只能将备忘录传递给其他对象;而Originator却可看到备忘录的宽接口,允许它访问返回到先前状态所需要的所有数据。

2. Originator(原发器)

originator创建一个备忘录,用以记录当前时刻它的内部状态。

使用备忘录回复内部状态。

只有创建备忘录的原发器会对他的状态状态进行赋值和检索。

3. Caretaker(负责人)

负责保存好备忘录。

不能对备忘录的内容进行操作或检查。

负责保存与提供备忘录对象,但是不能对备忘录的内容进行访问或者操作。

类图

在这里插入图片描述

代码示例

package com.polaris.designpattern.list3.behavioral.pattern08.memento.classicdemo;// 备忘录接口
interface Memento {// 可能包含一些用于获取状态的方法  String getState();
}// 发起人(Originator)  
class Originator {private String state;// 创建一个备忘录并保存当前状态  public Memento createMemento() {return new MementoImpl(state);}// 恢复发起人状态  public void restoreMemento(Memento memento) {this.state = ((MementoImpl) memento).getState();}// 设置发起人状态  public void setState(String state) {this.state = state;}// 获取发起人状态  public String getState() {return state;}// 备忘录实现类,仅供发起人使用  private static class MementoImpl implements Memento {private String state;public MementoImpl(String state) {this.state = state;}public String getState() {return state;}}
}// 管理者(Caretaker)  
class Caretaker {private Memento memento;// 保存备忘录  public void setMemento(Memento memento) {this.memento = memento;}// 获取备忘录  public Memento getMemento() {return memento;}
}// 使用示例  
public class MementoPatternDemo {public static void main(String[] args) {Originator originator = new Originator();Caretaker caretaker = new Caretaker();originator.setState("State #1");System.out.println("Current State: " + originator.getState());// 保存当前状态  caretaker.setMemento(originator.createMemento());originator.setState("State #2");System.out.println("Current State: " + originator.getState());// 恢复之前的状态  originator.restoreMemento(caretaker.getMemento());System.out.println("Restored State: " + originator.getState());}
}/* Output:
Current State: State #1
Current State: State #2
Restored State: State #1
*///~

在这个例子中,Originator类维护了一个内部状态state,并提供了创建备忘录(createMemento)和恢复状态(restoreMemento)的方法。备忘录的实际实现是MementoImpl类,但它被声明为Originator的私有内部类,因此外部类(如Caretaker)不能直接访问它。Caretaker类负责管理备忘录对象。在MemontoPatternDemo类中,我们展示了如何使用这些类来保存和恢复Originator的状态。

备忘录模式的应用

备忘录模式,又称之为快照模式(Snapshot Pattern),是一种软件设计模式,主要用于保存和恢复对象的内部状态。以下是其主要应用:

  1. 撤销和恢复功能:在Word、PhotoShop等软件中,用户可以撤销之前的操作,或恢复到某个历史状态。备忘录模式能够记录用户的每一步操作,从而实现这一功能。
  2. 电子书的阅读进度:用户在阅读电子书时,可以随时保存阅读进度,下次打开时可以从上次的阅读进度继续阅读。
  3. 软件开发中的版本控制:记录每个版本的代码快照,方便进行版本控制和回溯。
  4. 事务管理:在数据库事务处理中,如果一系列操作不能全部完成,就需要回滚操作,将数据恢复到操作之前的状态。备忘录模式可以记录一系列操作的快照,当需要回滚时,可以恢复到备忘录状态。

备忘录模式的优点

  1. 提供恢复机制:为用户提供一种可以恢复状态的机制,允许在必要时将对象恢复到之前的状态。
  2. 实现内部状态的封装:除了创建它的发起人之外,其他对象都不能够访问这些状态信息,这有助于保持封装的边界。
  3. 简化发起人类:发起人不需要管理和保存其内部状态的各个备份,所有状态信息都保存在备忘录中,并由管理者进行管理,这符合单一职责原则。

备忘录模式的缺点

  1. 资源消耗大:如果要保存的内部状态信息过多或者特别频繁,将会占用比较大的内存资源。
  2. 难以预测存储需求:当负责人角色将一个备忘录存储起来的时候,可能无法预测这个状态会占用多大的存储空间,从而无法提醒用户一个操作是否很昂贵。

备忘录模式的使用场景

备忘录模式适用于需要保存/恢复数据的相关业务场景,如:

  1. 撤销操作:在文本编辑器、图形编辑器等工具中,用户可能需要撤销之前的操作。
  2. 游戏存档:在游戏中,玩家可能需要存档以便在之后恢复游戏进度。
  3. 数据库事务管理:在数据库事务处理中,如果一系列操作不能全部完成,就需要回滚操作,将数据恢复到操作之前的状态。

---

👈️上一篇:观察者模式

设计模式-专栏👈️

相关文章:

  • 为什么说Python 是胶水语言?
  • C# OpenCvSharp 代数运算-add、scaleAdd、addWeighted、subtract、absdiff、multiply、divide
  • 大型企业IT基础架构和应用运维体系
  • 基于Java的诊所医院管理系统,springboot+html,MySQL数据库,用户+医生+管理员三种身份,完美运行,有一万一千字论文
  • 【DevOps】Logstash详解:高效日志管理与分析工具
  • macOS Sequoia 将 Mac 生产力与智能化提升至全新高度 (macOS 15 ISO、IPSW、PKG 下载)
  • 69. UE5 RPG 使用Gameplay Cue 实现技能表现效果
  • 9M高速USB转接芯片CH347转双串口转I2C转SPI转JTAG转SWD
  • Linux内核中的锁
  • 判断QT程序是否重复运行
  • Qt自定义日志输出
  • 【MySQL】索引(上)
  • 如何连接达梦数据库?
  • java框架技术xml文件存档
  • CSS语言笔记
  • .pyc 想到的一些问题
  • ES6简单总结(搭配简单的讲解和小案例)
  • java正则表式的使用
  • java中的hashCode
  • JS+CSS实现数字滚动
  • Linux学习笔记6-使用fdisk进行磁盘管理
  • Map集合、散列表、红黑树介绍
  • Markdown 语法简单说明
  • spring学习第二天
  • Vue小说阅读器(仿追书神器)
  • webpack项目中使用grunt监听文件变动自动打包编译
  • 从@property说起(二)当我们写下@property (nonatomic, weak) id obj时,我们究竟写了什么...
  • 基于Vue2全家桶的移动端AppDEMO实现
  • 极限编程 (Extreme Programming) - 发布计划 (Release Planning)
  • 坑!为什么View.startAnimation不起作用?
  • 每天10道Java面试题,跟我走,offer有!
  • 前端性能优化——回流与重绘
  • 前端自动化解决方案
  • 如何抓住下一波零售风口?看RPA玩转零售自动化
  • 手机端车牌号码键盘的vue组件
  • 吐槽Javascript系列二:数组中的splice和slice方法
  • 微信如何实现自动跳转到用其他浏览器打开指定页面下载APP
  • 详解移动APP与web APP的区别
  • ​MySQL主从复制一致性检测
  • #免费 苹果M系芯片Macbook电脑MacOS使用Bash脚本写入(读写)NTFS硬盘教程
  • ( 10 )MySQL中的外键
  • (06)Hive——正则表达式
  • (2021|NIPS,扩散,无条件分数估计,条件分数估计)无分类器引导扩散
  • (2024,LoRA,全量微调,低秩,强正则化,缓解遗忘,多样性)LoRA 学习更少,遗忘更少
  • (免费领源码)Python#MySQL图书馆管理系统071718-计算机毕业设计项目选题推荐
  • (三)Honghu Cloud云架构一定时调度平台
  • (五)IO流之ByteArrayInput/OutputStream
  • (一)ClickHouse 中的 `MaterializedMySQL` 数据库引擎的使用方法、设置、特性和限制。
  • (源码版)2024美国大学生数学建模E题财产保险的可持续模型详解思路+具体代码季节性时序预测SARIMA天气预测建模
  • (转)EXC_BREAKPOINT僵尸错误
  • (转)关于pipe()的详细解析
  • .netcore 获取appsettings
  • .NET处理HTTP请求
  • .NET开源的一个小而快并且功能强大的 Windows 动态桌面软件 - DreamScene2
  • .NET平台开源项目速览(15)文档数据库RavenDB-介绍与初体验