设计模式: 行为型之备忘录模式(13)

备忘录模式概述

  • 备忘录模式(Memento Pattern)是一种行为设计模式,它允许在不破坏封装性的前提下捕获一个对象的内部状态,并在对象之外保存这个状态
  • 这样以后就可将该对象恢复到原先保存的状态。这种类型的设计模式属于行为模式
  • 在备忘录模式中,主要涉及三种角色:
    • 发起人(Originator)角色
      • 记录当前时刻它的内部状态,并可使用备忘录恢复内部状态
      • 发起人可以根据需要决定备忘录存储发起人的哪些状态
    • 备忘录(Memento)角色
      • 负责存储发起人对象的内部状态,并可防止发起人以外的其他对象访问备忘录
      • 备忘录有两个接口,一是提供它所能保存的发起人内部状态,二是将这些状态恢复到发起人对象中
    • 管理者(Caretaker)角色
      • 负责保存好备忘录,不能对备忘录的内容进行操作或检查

备忘录模式应用

// 原始类(Originator)定义
class Originator {private state: string; // 内部状态constructor(state: string) {this.state = state;}// 创建备忘录方法,返回备忘录对象createMemento(): Memento {return new Memento(this.state);}// 设置内部状态方法,可以通过备忘录恢复状态setMemento(memento: Memento) {this.state = memento.getState();}// 其他业务逻辑,改变内部状态setState(newState: string) {this.state = newState;console.log(`State changed to: ${this.state}`);}// 获取当前状态getState(): string {return this.state;}
}// 备忘录接口和实现
interface Memento {getState(): string;
}class ConcreteMemento implements Memento {private _state: string;constructor(state: string) {this._state = state;}getState(): string {return this._state;}
}// 管理者角色(Caretaker)负责保管备忘录,但不关心备忘录的具体内容
class Caretaker {private _mementos: Memento[] = [];// 添加备忘录addMemento(memento: Memento) {this._mementos.push(memento);}// 获取备忘录,通常由原始类调用getMemento(index: number): Memento | undefined {return this._mementos[index];}
}// 示例用法
const originator = new Originator("Initial State");
console.log("Original state:", originator.getState());// 创建一个备忘录并保存状态
const caretaker = new Caretaker();
caretaker.addMemento(originator.createMemento());// 改变原始类的状态
originator.setState("New State");
console.log("Changed state:", originator.getState());// 通过备忘录恢复状态
if (caretaker.getMemento(0)) {originator.setMemento(caretaker.getMemento(0)!);console.log("Restored state:", originator.getState());
}
  • 在这个例子中:Originator 类代表了一个包含内部状态的对象,它定义了如何创建 (createMemento) 和恢复 (setMemento) 备忘录。
  • Memento 是一个接口,代表备忘录对象,它包含了对内部状态的引用,但对外部世界隐藏了这些状态的具体内容。ConcreteMemento 类实现了这个接口,存储了实际的状态值。
  • Caretaker 类扮演管理者角色,它可以接收备忘录并存储它们,但它并不知道如何解读备忘录的内容。当需要时,它把备忘录交还给 Originator 进行状态恢复。
  • 通过这种模式,我们可以安全地保存和恢复 Originator 的内部状态,同时保持了良好的封装性

备忘录模式的优缺点


1 )优点

  • 它提供了一种可以撤销操作的机制
  • 封装了内部状态,并通过对外部提供的接口来恢复内部状态

2 ) 缺点

  • 如果发起人状态很大或者很多,那么存储起来可能会消耗很大的内存
  • 可能会存在很多备忘录对象,消耗内存
  • 在实际应用中,备忘录模式通常用于实现诸如“撤销”这样的功能,例如文本编辑器中的撤销操作
  • 通过保存用户每次编辑操作的状态,可以方便地撤销到之前的状态

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

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

相关文章

【Qt 学习笔记】Qt常用控件 | 按钮类控件Push Button的使用及说明

博客主页:Duck Bro 博客主页系列专栏:Qt 专栏关注博主,后期持续更新系列文章如果有错误感谢请大家批评指出,及时修改感谢大家点赞👍收藏⭐评论✍ Qt常用控件 | 按钮类控件Push Button的使用及说明 文章编号&#xff1…

2024年华中杯数学建模竞赛全攻略:ABC题思路解析+代码实现+数据集+论文撰写+全程答疑

引言 (比赛后所有题目资料在文末获取呀) 华中杯数学建模竞赛是数学建模领域的一项重要赛事,它不仅考验参赛者的数学建模能力,还考验了编程技能、数据分析能力和论文撰写能力。为了帮助参赛者更好地准备2024年的竞赛,本…

libftdi1学习笔记 6 - MPSSE QSPI

目录 1. 写 2. 读 3. 验证 QSPI采用4根线为数据口,SCK和CS保留同样的功能,一般4个数据线采用MSB的方式发送数据,即高位在前。 QSPI只能是半双工工作。 1. 写 int qspiWriteBytes(uint8_t port, uint8_t* wrBuf, uint16_t l…

RAG学习笔记系列(一)

RAG 介绍 RAG 全称为 Retrieval Augmented Generation(检索增强生成)。是基于LLM构建系统的一种架构。 RAG 基本上可以理解为:搜索 LLM prompting。根据用户的查询语句,系统会先使用搜索算法获取到相关内容作为上下文&#xff0…

JavaScript如何设置定时器,怎么清除定时器

在JavaScript中,你可以使用setTimeout()和setInterval()函数来设置定时器,以及使用clearTimeout()和clearInterval()函数来清除定时器。 setTimeout() setTimeout()函数用于在指定的毫秒数之后执行一个函数或计算表达式。它返回一个表示定时器的ID&…

pnpm 报错: ERR_PNPM_META_FETCH_FAIL

今天突然遇到一个报错,pnpm 报错: ERR_PNPM_META_FETCH_FAIL  GET https://registry.npm.taobao.org/vue%2Fcli-service: request to https://registry.npm.taobao.org/vue%2Fcli-service failed, reason: certificate has expired问题原因:…

when语法学习及判断主机别名实例

目录 1、概念 2、实例配置 2.1 编写剧本体验when的用法 2.2 执行剧本文件 2.3 使用ansible临时命令进行测试 1、概念 when是用于判断的语法,将其用在每个动作的下方进行判断,使得只有在满足条件才会执行。 2、实例配置-判断主机别名 在每个客户端中…

移动端uniapp下载文件并保存到手机,下载准考证保存到手机

移动端uniapp下载文件并保存到手机,下载准考证保存到手机 1. 使用uni.request下载文件 uni.request({ url: http://example.com/file_url, // 要下载的文件的URL method: GET, responseType: arraybuffer, // 响应类型为arraybuffer (二进制形式) success: functi…

Compose 基础组件

文章目录 Compose 基础组件Modifier 修饰符Scaffold 脚手架 Compose 基础组件 Modifier 修饰符 在传统视图体系中,使用XML文件描述组件的样式,而在Compose中使用Modifier,每个基础的Composable组件都有一个modifier参数,通过Mod…

使用CCS软件查看PID曲线

在刚开始学习PID的时候,都需要借助PID的曲线来理解比例,积分,微分这三个参数的具体作用。但是这些曲线生成一般都需要借助上位机软件或者在网页上才能实现。如果是在单片机上调试程序的话,想要看曲线,一般就是通过串口…

【YOLOv5】使用yolov5训练模型时报错合集

文章目录 前言问题1 -- VsCode终端无法进入Anaconda创建的虚拟环境【问题描述】【问题分析】【解决方式】方法一方法二 问题2 -- 怎么在VsCode中为项目配置Anaconda创建的虚拟环境【问题描述】【解决方式】 问题3 -- yolov5训练模型时报错RuntimeError: result type Float cant…

web自动化测试系列-selenium常用方法定位(五)

目录 1.selenium的定位方法 2.操作案例 3.实现代码 前面我们介绍了html页面元素主要是通过标签和属性来进行定位 ,只要满足唯一,无论是标签还是属性 ,都能进行定位 。当然 ,我们要通过selenium来进行定位 ,同样还是…

富格林:利用正规方法提升出金收益

富格林悉知,黄金现货是众多黄金产品当中交易规则优势较为明显的存在,尤其是近段时间的行情走势十分强劲,这使得投资者们获得了更充足的做单机会。然而,要想在炒黄金的市场上取得成功,除了对市场有深刻的理解外&#xf…

总结:css中水平居中

css水平居中功能很常用,但一直没有系统的总结过,今天来总结水平下常见的方式: 1. 文本或内联元素的居中: 使用 text-align: center; 属性可以让内部的文本和内联元素在容器中水平居中。 .container {text-align: center; }2. 块…

小公司应该选择docker swarm还是k8s

对于小公司选择 Docker Swarm 还是 Kubernetes(简称 K8s)作为容器编排平台,应考虑以下几个关键因素: 技术复杂度与学习曲线: Docker Swarm:因其与 Docker 紧密集成,使用 Docker Compose 语法作…

MongoDB聚合运算符:$ne

文章目录 语法举例 $ne聚合运算符用于比较两个值是否不相等&#xff0c;如果他们的值不相等&#xff0c;返回true&#xff1b;如果他们的值相等&#xff0c;返回false。 语法 { $ne: [ <expression1>, <expression2> ] }$ne可以用来比较任何类型的值&#xff0c;…

【C++风云录】梦幻般的机器人世界:探索ROS、PCL、OpenCV和更多顶尖技术

机器人技术与计算机视觉世界&#xff1a;ROS、PCL、OpenCV等综合指南 前言 本文旨在深入探讨ROS&#xff08;机器人操作系统&#xff09;、PCL&#xff08;点云库&#xff09;、OpenCV&#xff08;开源计算机视觉库&#xff09;、Eigen&#xff08;线性代数库&#xff09;、B…

基于SpringBoot的在线五子连珠的设计与实现,前端采用vue框架;后端采用SpringBoot,mybatis

介绍 基于SpringBoot的在线五子连珠的设计与实现&#xff0c;主要是设计一款五子棋游戏&#xff0c;涉及登录注册的功能&#xff0c;人机对战、联机对战和积分排行榜的功能。其中人机对战中&#xff0c;电脑采用的是采用了一种基于局面分析的评分算法来确定机器人的下一步落子…

线程池学习(通俗易懂)

线程池 线程池是什么ThreadPoolExecutor模拟实现线程池结语 线程池是什么 假设我们要频繁的创建线程和销毁线程,但是创建线程和销毁线程是有成本的. 所以我们可以提前创建一批线程,后面需要使用的时候,直接拿就可以了,这就是线程池. 当线程不再使用的时候,就归还到池子里.为什…

图片懒加载

看下tuniu的页面&#xff0c;这有两个属性src和data-src <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta name"viewport" content"widthdevice-width, initial-scale1.0" /><t…