设计模式-10 - Memento Design Pattern

设计模式-10 - Memento Design Pattern 
 

1.定义


备忘录模式是一种设计模式,它允许在不破坏封装性的情况下捕获和恢复对象的内部状态。

其结构:

Originator:创建和管理备忘录的对象。
Memento:存储 Originator 状态的备忘录对象。Memento 对象是不可变的。
Caretaker:存储 Memento 对象,而不了解其实际内容。

示例:

一个文本编辑器可以使用备忘录模式来存储文档的状态,以便用户可以撤消和重做编辑操作。Originator 是文档对象,Memento 是存储文档状态的文本快照,Caretaker 是管理备忘录的撤消/重做管理器。

        +--------------+| Originator   |+--------------+|v+--------------+| Memento      |+--------------+|v+--------------+| Caretaker    |+--------------+|v(stores Memento)

调用关系:

  • Originator 创建一个 Memento 对象来存储其当前状态。
  • Caretaker 从 Originator 接收 Memento 对象并将其存储起来。
  • Originator 修改其状态。
  • Originator 从 Caretaker 恢复其状态,传递先前创建的 Memento 对象。
  • Caretaker 将 Memento 对象传递给 Originator。
  • Originator 使用 Memento 对象恢复其状态。

说明:

Originator:创建和修改其状态,并创建 Memento 对象来存储其状态。
Memento:存储 Originator 的状态,以便以后可以恢复。
Caretaker:负责存储和管理 Memento 对象。

            

2.内涵

工作原理:

Originator 创建一个 Memento 对象,该对象捕获其当前状态。
Originator 可以将 Memento 对象传递给 Caretaker。
当 Originator 需要恢复其状态时,它可以从 Caretaker 请求 Memento 对象。
Originator 使用 Memento 对象恢复其内部状态。

3.使用示例
#include <iostream>
#include <string>
#include <vector>// Originator: The object whose state needs to be saved and restored.
class Originator {
private:std::string state;public:void SetState(const std::string& newState) {state = newState;}std::string GetState() const {return state;}// Memento: Inner class representing the state of the Originator.class Memento {private:std::string state;public:Memento(const std::string& originatorState) : state(originatorState) {}std::string GetSavedState() const {return state;}};// Create a Memento object to save the current state.Memento CreateMemento() const {return Memento(state);}// Restore the state from a Memento object.void RestoreState(const Memento& memento) {state = memento.GetSavedState();}
};// Caretaker: Manages the Memento objects.
class Caretaker {
private:std::vector<Originator::Memento> mementos;public:void AddMemento(const Originator::Memento& memento) {mementos.push_back(memento);}Originator::Memento GetMemento(int index) const {if (index >= 0 && index < mementos.size()) {return mementos[index];}throw std::out_of_range("Invalid Memento index");}
};int main() {Originator originator;Caretaker caretaker;originator.SetState("State 1");caretaker.AddMemento(originator.CreateMemento());originator.SetState("State 2");caretaker.AddMemento(originator.CreateMemento());// Restore to the previous stateoriginator.RestoreState(caretaker.GetMemento(0));std::cout << "Current state: " << originator.GetState() << std::endl;// Restore to an even earlier stateoriginator.RestoreState(caretaker.GetMemento(1));std::cout << "Current state: " << originator.GetState() << std::endl;return 0;
}

4.注意事项

备忘录模式需要注意的事项:

  • 只存储相关状态:Memento 对象应仅存储 Originator 的相关状态,而不是其所有状态。这有助于保持 Memento 的大小较小并提高性能。
  • 避免存储引用:Memento 对象不应存储对其他对象的引用,因为这可能会导致循环引用和内存泄漏。
  • 考虑序列化:如果需要在进程或计算机之间传输 Memento 对象,则需要考虑序列化和反序列化机制。
  • 版本控制:如果 Originator 的状态可能会随着时间的推移而改变,则需要考虑使用版本控制机制来管理 Memento 对象的不同版本。
  • 并发访问:在并发环境中使用备忘录模式时,需要确保 Originator、Memento 和 Caretaker 类都是线程安全的,并且并发访问备忘录是原子的。
  • 性能影响:频繁创建和存储 Memento 对象可能会对应用程序的性能产生影响,尤其是在处理大型或复杂的状态时。
  • 设计复杂性:备忘录模式可能会增加应用程序的设计复杂性,尤其是在需要管理多个 Originator 和 Memento 对象时

5.最佳实践

当需要以下场景时,需要使用备忘录设计模式:

  • 当需要在不破坏封装性的情况下捕获和恢复对象的内部状态时。
  • 当需要多次撤消和重做操作时。
  • 当需要将复杂的对象图存储为快照时。

6.总结


在设计一个需要频繁保存状态的应用,如何确保备忘录模式在并发环境中有效应对并发访问,这里有些方法可以借鉴:

  • 线程安全:确保 Originator、Memento 和 Caretaker 类都是线程安全的。这可以采用多种方法实现,例如使用同步机制(例如锁或互斥量)或使用不可变对象。
  • 只读备忘录:使 Memento 对象不可变。这将防止并发访问时意外修改备忘录的内容。
  • 并发控制:在 Caretaker 中使用适当的并发控制机制,例如读写锁或原子操作,以确保对备忘录的访问是原子的。
  • 隔离备忘录:为每个 Originator 实例维护一个单独的备忘录存储。这将防止不同 Originator 实例之间的并发访问冲突。
  • 使用版本控制:为备忘录引入版本控制机制。这将允许跟踪和恢复备忘录的不同版本,即使在并发访问的情况下也是如此。


其他考虑因素:

  • 性能:在高并发环境中,确保备忘录模式的实现不会引入明显的性能开销。
  • 可扩展性:备忘录模式的实现应该具有可扩展性,以便在需要时可以轻松扩展以支持更多的并发访问。
  • 测试:彻底测试备忘录模式的实现,以确保其在并发环境中按预期工作。

通过遵循这些准则,你可以确保备忘录模式在需要频繁保存状态的并发应用程序中能有效应对并发访问。

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

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

相关文章

品牌设计理念和logo设计方法

一 品牌设计的目的 设计是为了传播&#xff0c;让传播速度更快&#xff0c;传播效率更高&#xff0c;减少宣传成本 二 什么是好的品牌设计 好的设计是为了让消费者更容易看懂、记住的设计&#xff0c; 从而辅助传播&#xff0c; 即 看得懂、记得住。 1 看得懂 就是让别人看懂…

树莓派|采集视频并实时显示画面

1、使用SSH远程连接到树莓派 2、新建存放代码的目录 mkdir /home/pi/my_code_directory 3、进入存放代码的目录 cd /home/pi/my_code_directory 4、新建py文件 nano cv2test.py 5、输入代码 import cv2# 打开摄像头 cap cv2.VideoCapture(0)while True:# 读取视频帧ret…

BGP学习二:BGP通告原则,BGP反射器,BGP路径属性细致讲解,新手小白无负担

目录 一.AS号 二.BGP路由生成 1.network 2.import-route引入 三.BGP通告原则 1.只发布最优且有效的路由 2.从EBGP获取的路由&#xff0c;会发布给所有对等体 3.水平分割原则 4.IBGP学习BGP默认不发送给EBGP&#xff0c;但如果也从IGP学习到了这条路由&#xff0c;就发…

mysql 幻读,脏读和不可重复读

MySQL的脏读、幻读和不可重复读是数据库事务处理中的三种常见问题&#xff0c;它们都涉及到数据的一致性和并发性。一&#xff0c;脏读 脏读是指一个事务读取了另一个事务未提交的数据。这可能导致数据不一致的问题。 例如&#xff1a; 用户user1的初始balance是100&#xff0…

java项目之智慧图书管理系统设计与实现(springboot+vue+mysql)

风定落花生&#xff0c;歌声逐流水&#xff0c;大家好我是风歌&#xff0c;混迹在java圈的辛苦码农。今天要和大家聊的是一款基于springboot的智慧图书管理系统设计与实现。项目源码以及部署相关请联系风歌&#xff0c;文末附上联系信息 。 项目简介&#xff1a; 智慧图书管理…

SOCKET编程(5):IO复用

IO复用 多进程/线程并发模型&#xff0c;为每个sockets分配一个进程/线程 I/O&#xff08;多路&#xff09;复用&#xff0c;采用单个进/线程就可以管理多个socket I/O复用有3种方案&#xff1a; selectpollepoll select I/O多路复用详解 27、fd_set与FD_SETSIZE详解 详解…

新闻资讯微信小程序开发后端+php【附源码,文档说明】

博主介绍&#xff1a;✌IT徐师兄、7年大厂程序员经历。全网粉丝15W、csdn博客专家、掘金/华为云//InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;&#x1f3…

管理科学SCI、SSCI双检索,自引率低,无预警风险,对国人相当友好!

一、期刊名称 Journal of Organizational and End User Computing 二、期刊简介概况 期刊类型&#xff1a;SSCI 学科领域&#xff1a;管理学 影响因子&#xff1a;6.5 中科院分区&#xff1a;2区 出版方式&#xff1a;开放出版 版面费&#xff1a;$3300 三、期刊征稿范围…

探秘钱塘高中,筑梦未来之旅————杭州市钱塘高级中学

晨曦微露&#xff0c;书生琅琅&#xff0c;古韵今风交织在这方学府&#xff0c;滔滔的钱塘江畔&#xff0c;杭州市钱塘高级中学屹立于此。这所学校自1958年建校伊始&#xff0c;走过几十年的光辉岁月&#xff0c;一直致力于提供优质的教育资源。 近年来&#xff0c;学校获得多项…

Learning C# Programming with Unity 3D

作者&#xff1a;Alex Okita 源码地址&#xff1a;GitHub - badkangaroo/UnityProjects: A repo for all of the projects found in the book. 全书 686 页。

Java常见数据结构---八大结构

前言&#xff1a; 数据结构是计算机底层存储、组织数据的方式。是指数据相互之间是以什么方式排列在一起的。 通常情况下&#xff0c;精心选择的数据结构可以带来更高的运行或者存储效率 常见的八大数据结构&#xff1a; 栈&#xff1a; 思想&#xff1a; 栈是一种数据结构&…

大数据项目中的拉链表(hadoop,hive)

缓慢渐变维 拉链表 拉链表&#xff0c;可实现数据快照&#xff0c;可以将历史和最新数据保存在一起 如何实现: 在原始数据增加两个新字段 起始时间&#xff08;有效时间&#xff1a;什么时候导入的数据的时间&#xff09;&#xff0c;结束时间&#xff08;默认的结束时间为99…

运筹系列92:vrp算法包VROOM

1. 介绍 VROOM is an open-source optimization engine written in C20 that aim at providing good solutions to various real-life vehicle routing problems (VRP) within a small computing time. 可以解决如下问题&#xff1a; TSP (travelling salesman problem) CVRP …

九、 个人信息出境标准合同的签署及备案流程是怎样的?

为指导和帮助个人信息处理者规范有序备案个人信息出境标准合同&#xff0c;国家网信办结合此前备案实践经验发布了《标准合同备案指南&#xff08;第二版&#xff09;》&#xff0c;并就个人信息出境标准合同备案的适用范围、备案方式、备案流程和材料以及咨询、举报联系方式等…

F5 BIG-IP Next Central Manager SQL注入漏洞(CVE-2024-26026、CVE-2024-21793)

0x01 产品简介 BIG-IP Next Central Manager是BIG-IP Next的原生默认用户界面,它可跨平台管理BIG-IP Next实例。BIG-IP Next是F5 Networks公司推出的一款下一代BIG-IP软件,提供了多云应用安全和应用交付服务。 0x02 漏洞概述 CVE-2024-26026:BIG-IP Next Central Manager…

产品推荐 | 基于AMD Virtex 7 FPGA VC709 的高速连接功能开发板

01 产品概述 Virtex™ 7 FPGA VC709 连接功能套件是一款速率为 40Gb/s 的高速平台&#xff0c;您可以通过评估和开发连接功能&#xff0c;迅速为包含所有必要软硬件和 IP 核的高带宽和高性能应用提供强大的支持。它包括一个含有 PCI Express Gen 3、Northwest Logic 公司推出的…

4.1 文本相似度(二)

目录 1 文本相似度评估 2 代码 2.1 load_dataset 方法 2.2 AutoTokenizer、AutoModelForSequenceClassification 1 文本相似度评估 对两个文本拼接起来&#xff0c;然后作为一个样本喂给模型&#xff0c;作为一个二分类的任务&#xff1b; 数据处理的方式以及训练的基本流程…

c 指针基础

/* 指针练习*/ #include <stdio.h> #include <stdlib.h> void printAll(int n1, int n2, int *p1, int *p2); int main(){ //赋值操作语法演示 int num1 1111; int num2 2222; int *prt1 &num1; int *prt2 &num2; printAll(num1, num2, prt1…

maven .lastUpdated文件作用

现象 有时候我在用maven管理项目时会发现有些依赖报错&#xff0c;这时你可以看一下本地仓库中是否有.lastUpdated文件&#xff0c;也许与它有关。 原因 有这个文件就表示依赖下载过程中发生了错误导致依赖没成功下载&#xff0c;可能是网络原因&#xff0c;也有可能是远程…

平面设计基础指南:从零开始的学习之旅!

平面设计师主要做什么&#xff1f; 平面设计师通过创建视觉概念来传达信息。他们创造了从海报和广告牌到包装、标志和营销材料的所有内容&#xff0c;并通过使用形状、颜色、排版、图像和其他元素向观众传达了他们的想法。平面设计师可以在内部工作&#xff0c;专门为品牌创建…