.NET 设计模式—备忘录模式(Memento Pattern)

简介

        备忘录模式,又称之为快照模式(Snapshop Pattern),是一种行为型设计模式,,它允许在不破坏对象封装性的前提下,捕获并保存一个对象的内部状态,以便在需要时恢复该对象到原先的状态。备忘录模式可以为我们提供一种“后悔药”的机制,它通过存储系统中各个历史状态的快照,使得我们可以在任一时刻将系统回滚到历史状态。

角色

  • 发起人(Originator):发起人角色记录当前时刻的内部状态信息,提供创建备忘录和恢复备忘录数据的功能,实现其他业务功能。
  • 备忘录(Memento):备忘录角色负责存储发起人的内部状态,在需要的时候提供这些内部状态给发起人
  • 管理者(Caretaker):管理者角色对备忘录进行管理,提供保存与获取备忘录的功能,但其不能对备忘录的内容进行访问与修改。

优点

  • 可以随时保存一个对象的状态,并在需要时恢复到该状态,提高了程序的灵活性和可维护性;
  • 发起人和备忘录之间的封装使得客户端无法直接访问备忘录,从而更好地保护了对象的状态信息;
  • 管理者可以管理多个备忘录,提供了更好的历史记录和回滚功能。

缺点

  • 备忘录模式的缺点包括:如果备忘录对象过多或者状态信息过于复杂,会占用较多的内存空间;
  • 捕获和恢复一个对象的状态需要时间和资源,可能会影响程序的性能;

应用场景

  • 保存和恢复对象状态:在软件中,有些对象的状态需要在不同时间点进行保存和恢复。备忘录模式可以捕获对象的状态,并在需要时恢复对象到先前的状态。例如,在浏览器中的后退功能,或者在编辑工具中的撤销操作等。
  • 实现可回滚的撤销操作:在软件中,撤销操作是一个常见的功能。备忘录模式可以保存对象的状态,以便在撤销操作时恢复对象到先前的状态。例如,在Word中编写文档,如果想要撤销之前的输入/删除操作,可以使用备忘录模式实现可回滚的撤销操作。

实现

  • 定义发起人(Originator)
public class Originator
{// 发起人的内部状态信息private string state;public string State{get { return state; }set { state = value; }}// 保存状态到备忘录的方法public Memento SaveToMemento(){// 这里可以根据需要序列化状态信息到备忘录对象中return new Memento(state); // 假设Memento类有一个构造函数接收状态信息}// 从备忘录中恢复状态的方法public void RestoreFromMemento(Memento memento){// 这里可以根据备忘录中的信息反序列化状态到发起人对象中State = memento.GetState(); // 假设Memento类有一个GetState方法返回状态信息}
}
  • 定义备忘录(Memento)
public class Memento
{private string state; // 存储状态信息的字段,可以是任何类型,视具体情况而定。public Memento(string state) // 构造函数接收状态信息{this.state = state;}public string GetState() // 提供获取状态信息的方法{return state;}
}
  • 定义管理者(Caretaker)
public class Caretaker
{private Memento memento; // 存储备忘录的字段。// 保存备忘录的方法,由外部调用以保存发起人的状态。public void Save(Originator originator){memento = originator.SaveToMemento(); // 保存发起人的当前状态到备忘录中。}// 恢复备忘录的方法,由外部调用以恢复发起人的状态。public void Restore(Originator originator){originator.RestoreFromMemento(memento); // 使用保存的备忘录恢复发起人的状态。}
}
  • 上层应用调用
Originator originator = new Originator(); // 创建发起人对象。
Caretaker caretaker = new Caretaker(); // 创建管理者对象。
originator.State = "初始状态"; // 设置发起人的初始状态。
caretaker.Save(originator); // 保存当前状态到备忘录。
// ... 可能进行一些操作改变originator的状态 ...
originator.State = "改变后的状态"; // 发起人状态改变。
caretaker.Restore(originator); // 通过备忘录恢复至之前保存的状态。

在这个案例中,Originator 类负责维护其内部状态,Memento 类存储这些状态信息,而 Caretaker 类负责在需要时保存和恢复这些状态。这种方式允许在不破坏封装性的前提下管理对象的历史状态。

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

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

相关文章

一台服务器同时启动两个版本jdk

之前Java项目都是1.8的jdk,在服务器部署正常使用,服务器配置环境变量jdk1.8版本。最近一次我用了jdk17版本,部署服务器后,遇见了jdk版本不一致报错 报错内容: 52指向jdk1.8,61指向jdk17,大概就是jdk版本不…

[Java基础揉碎]集合

目录 集合的理解和好处 数组 集合的理解和好处 继承图 ​编辑 简单实例 Collection接口和常用方法 1) add:添加单个元素 2) remove:删除指定元素 3) contains:查找元素是否存在 4) size:获取元素个数 5) isEmpty:判断是否为空 ​编辑 6) clear:清空 7) addAll:添…

acwing算法提高之图论--二分图

目录 1 介绍2 训练3 参考 1 介绍 本专题用来记录二分图的题目。 以下条件互相等价: 一个图是二分图。染色法过程中不存在矛盾。图中不存在奇数环。 二分图本质上是一个无向图的问题! 2 训练 题目1:257关押罪犯 C代码如下, …

数组双指针

力扣26 快慢指针 去掉重复元素 数组 public int removeDuplicates(int[] nums) {int slow 0;int fast 1;int count 0;if (nums.length 1) {return 1;} else {while (fast < nums.length) {if (nums[slow] nums[fast]) {// 若相等 则 fast向前走 slow不动fast;}else{// …

「51媒体」新闻媒体邀约如何进行媒体宣传(方法)

传媒如春雨&#xff0c;润物细无声&#xff0c;大家好&#xff0c;我是51媒体网胡老师。 新闻媒体邀约进行媒体宣传是一个策略性的过程&#xff0c;旨在吸引媒体的注意力并促使其对特定事件、产品发布或企业活动进行报道。以下是一些关键步骤和策略&#xff1a; 制定媒体传播方…

【做一名健康的CSDNer】程序员脱单真的很难吗?

脱单的难易程度并不取决于一个人是否是程序员&#xff0c;而是受到多种因素的影响&#xff0c;包括个人的社交能力、生活方式、个性特点、外貌形象、兴趣爱好等。程序员这个职业群体并不例外。 对于程序员来说&#xff0c;可能面临的挑战包括&#xff1a; 工作时间&#xff1a;…

<计算机网络自顶向下> TCP拥塞

目录 TCP拥塞控制机制 TCP拥塞感知 TCP速率控制方法 TCP拥塞控制和流量控制的联合动作 TCP拥塞控制策略 TCP吞吐量 TCP公平性 TCP拥塞控制机制 端到端的拥塞控制机制 路由器不向主机提供有关拥塞的反馈信息 路由器负担较轻 符合网络核心简单的TCP/IP架构原则 端系统根据自…

Oracle使用内部包自定义创建表空间和用户

如果之前有类似的表空间,可以使用dbms自动生成对应的表空间和数据文件 select dbms_metadata.get_ddl(TABLESPACE,ts.tablespace_name) from dba_tablespaces ts; 可以使用类似的 SQL> set echo off SQL> spool /data/logs/create_tablespace.log SQL> select dbms…

python读取pdf表格并合并为excel

import pdfplumber import pandas as pd import os from openpyxl import load_workbook from datetime import datetime # page_chars最尾部的非空字符 def tail_not_space_char(page_chars):i -1while page_chars[i].get(text).isspace():i i - 1# print(page_chars[i].get…

asp.net core rabbitmq的基本使用

要在 .NET Core 应用程序中实现使用 RabbitMQ 发送和接收消息的简单示例&#xff0c;首先需要在开发机器上安装 RabbitMQ 服务器并运行它。接下来&#xff0c;我们将创建两个控制台应用程序&#xff1a;一个用于发送消息&#xff08;生产者&#xff09;&#xff0c;另一个用于接…

灵途科技荣获省级“专精特新”企业认定!

4月8日&#xff0c;湖北省经济和信息化厅发布了湖北省第六批专精特新中小企业公示名单&#xff0c;泛自动驾驶领域光电感知专家灵途科技荣获省级“专精特新”企业认定。 “专精特新”自2021年在全国各省市范围内贯彻执行&#xff0c;旨在推动形成一批具备专业化、精细化优势&a…

设计模式学习笔记 - 开源实战三(中):剖析Google Guava中用到的设计模式

概述 上篇文章&#xff0c;我通过 Google Guava 这样一个优秀的开源类库&#xff0c;讲解了如何在业务开发中&#xff0c;发现跟业务无关、可以复用的通用功能模块&#xff0c;并将它们抽离出来&#xff0c;设计成独立的类库、框架或功能组件。 本章再来学习下&#xff0c;Go…

【Hadoop3.3.6全分布式环境搭建】

说明: 完成Hadoop全分布式环境搭建,需准备至少3台虚拟机(master slave01 slave02)环境: VMWare + Centos7 + JDK1.8+ Hadoop3.3.6主机规划: 主节点:master从节点:slave01 , slave02 一、准备工作 1、所有主机安装jdk 上传jdk-8u171-linux-x64.tar.gz到/root目录下,然后…

AWS SAP(Certified Solutions Architect- Professional)认证题库详解(一)

很多朋友在做AWS认证的时候拿到题库之后,却不理解正确答案的原理,这里针对每一条答案都给了一个非常详细的解释,同时也会积累丰富的云计算架构的实践经验,保证看得懂,记得住,看完一遍之后就可以去考试了。  问题1 一家公司使用Amazon在单个m4.2xlarge AmazonEC2实例上…

改变图片的DPI和 清晰度

投稿时&#xff0c;我们的图片不满足要求&#xff0c;经常需要修改&#xff0c;这个博主讲解了几种方法&#xff0c;非常好。 【科研制图】如何快速修改图片符合投稿要求(分辨率300DPI等)及AI智能绘制高质量图片&#xff08;Upscayl软件&#xff09;_哔哩哔哩_bilibili

【java】26:JUnit

为什么需要 JUnit&#xff1a; 1.一个类有很多功能代码需要测试&#xff0c;为了测试&#xff0c;就需要写入到main方法中 2.如果有多个功能代码测试&#xff0c;就需要来回注销&#xff0c;切换很麻烦……… 3.如果可以直接运行一个方法&#xff0c;就方便很多&#xff0c;并且…

openssl3.2 - exp - 用base64后的字符串作为配置项的值

文章目录 openssl3.2 - exp - 用base64后的字符串作为配置项的值概述笔记配置项的值长度有限制 配置项的值不能是base64之后的直接值&#xff0c;需要处理之后才行。openssl配置项的值并不是所有可见字符都可以例子现在用的base64的类cipher_base64.hcipher_base64.cpp 现在用的…

ChatGPT研究论文提示词集合1-【主题选择与问题研究、文献综述】

点击下方▼▼▼▼链接直达AIPaperPass &#xff01; AIPaperPass - AI论文写作指导平台 目录 1.主题选择与问题定义 2.文献综述 3.书籍介绍 AIPaperPass智能论文写作平台 近期小编按照学术论文的流程&#xff0c;精心准备一套学术研究各个流程的提示词集合。总共14个步骤…

论文笔记:Large Language Model for Participatory Urban Planning

202402 arxiv 大模型城市规划 引入了一个基于LLM的多代理协作框架&#xff0c;模拟规划师和数千名具有不同特征和背景的居民&#xff0c;用于参与式城市规划——>生成考虑居民多样化需求的城市区域土地利用规划为了提高讨论的效率&#xff0c;论文采用了鱼缸讨论机制&#…

python——函数

概念 函数就是将一段具有独立功能的代码块整合到一个整体并命名&#xff0c;在需要的位置调用这个名称去完成对应的需求 定义函数 def 函数名&#xff08;参数&#xff09;&#xff1a;代码1......return 值函数名 函数名由编程人员自定义的&#xff0c;满足标识符命名规则…