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

Java设计模式:四、行为型模式-05:备忘录模式

文章目录

  • 一、定义:备忘录模式
  • 二、模拟场景:备忘录模式
  • 三、改善代码:备忘录模式
    • 3.1 工程结构
    • 3.2 备忘录模式模型结构图
    • 3.3 备忘录模式定义
      • 3.3.1 配置信息类
      • 3.3.2 备忘录类
      • 3.3.3 记录者类
      • 3.3.4 管理员类
    • 3.4 单元测试
  • 四、总结:备忘录模式

一、定义:备忘录模式

在这里插入图片描述

  • 备忘录模式:是以可以恢复或者说回滚,配置、版本、悔棋为核心功能的设计模式。
    • 这种设计模式属于行为模式。
    • 在功能实现上是以不破坏原对象为基础增加备忘录操作类,记录原对象的行为从而实现备忘录模式。
  • 备忘录模式的使用场景:后悔药、IDEA 编辑和撤销、小霸王游戏机存档,photoshop

二、模拟场景:备忘录模式

在这里插入图片描述

  • 模拟系统在发布上线的过程中记录线上配置文件用于紧急回滚。
    • 在大型互联网公司系统的发布上线一定是易用、安全、可处理紧急状况的,同时为了可以隔离线上和本地环境,一般会把配置文件抽取出来放到线上,避免有人误操作导致本地的配置内容发布出去。
      • 同时,线上的配置文件也会在每次变更的时候进行记录,包括:版本号、时间、MD5、内容信息和操作人。
    • 在后续上线时如果发现紧急问题,系统就会需要回滚操作,如果执行回滚那么也可以设置配置文件是否回滚。
      • 因为每一个版本的系统可能会带着一些配置文件的信息,这个时候就可以很方便的让系统与配置文件一起回滚操作。
    • 使用备忘录模式,模拟如何记录配置文件信息。

三、改善代码:备忘录模式

  • 备忘录的设计模式实现,重点在于不更改原有类的基础上,增加备忘录类存放记录。

3.1 工程结构

design-step-18
|——src|——main|--java|--com.lino.design|--Admin.java|--ConfigFile.java|--ConfigMemento.java|--ConfigOriginator.java|--test|--java|--com.lino.design.test|--ApiTest.java

3.2 备忘录模式模型结构图

在这里插入图片描述

  • 以上是工程结构的一个类图,其实相对来说并不复杂,除了原有的配置类 ConfigFile 以外,只新增加了三个类。
    • ConfigMemento:备忘录类,相当于是对原有配置类的扩展。
    • ConfigOriginator:记录者类,获取和返回备忘录类对象信息。
    • Admin:管理员类,用于操作记录备忘信息,比如你一些列的顺序执行了什么或者某个版本下的内容信息。

3.3 备忘录模式定义

3.3.1 配置信息类

ConfigFile.java

package com.lino.design;import java.util.Date;/*** @description: 配置文件*/
public class ConfigFile {/*** 版本号*/private String versionNo;/*** 内容*/private String content;/*** 时间*/private Date dateTime;/*** 操作人*/private String operator;public ConfigFile(String versionNo, String content, Date dateTime, String operator) {this.versionNo = versionNo;this.content = content;this.dateTime = dateTime;this.operator = operator;}public String getVersionNo() {return versionNo;}public void setVersionNo(String versionNo) {this.versionNo = versionNo;}public String getContent() {return content;}public void setContent(String content) {this.content = content;}public Date getDateTime() {return dateTime;}public void setDateTime(Date dateTime) {this.dateTime = dateTime;}public String getOperator() {return operator;}public void setOperator(String operator) {this.operator = operator;}
}
  • 配置类可以是任何形式的,这里只是简单的描述一个基本的配置内容信息。

3.3.2 备忘录类

ConfigMemento.java

package com.lino.design;/*** @description: 备忘录*/
public class ConfigMemento {private ConfigFile configFile;public ConfigMemento(ConfigFile configFile) {this.configFile = configFile;}public ConfigFile getConfigFile() {return configFile;}public void setConfigFile(ConfigFile configFile) {this.configFile = configFile;}
}
  • 备忘录是对原有配置类的扩展,可以设置和获取配置信息。

3.3.3 记录者类

ConfigOriginator.java

package com.lino.design;/*** @description: 记录者*/
public class ConfigOriginator {private ConfigFile configFile;public ConfigFile getConfigFile() {return configFile;}public void setConfigFile(ConfigFile configFile) {this.configFile = configFile;}public ConfigMemento saveMemento() {return new ConfigMemento(configFile);}public void getMemento(ConfigMemento configMemento) {this.configFile = configMemento.getConfigFile();}
}
  • 记录者类除了对 ConfigFile 配置类增加了获取和设置方法外,还增加了 保存 saveMemento()、获取 getMemento(ConfigMemento configMemento)
    • saveMemento():保存备忘录的时候会创建一个备忘录信息,并返回回去,交给管理者处理。
    • getMemento:获取之后并不是直接返回,而是把备忘录的信息交给现在的配置文件 this.configFile

3.3.4 管理员类

Admin.java

package com.lino.design;import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;/*** @description: 管理员*/
public class Admin {private int cursorIdx = 0;private List<ConfigMemento> mementoList = new ArrayList<>();private Map<String, ConfigMemento> mementoMap = new HashMap<>(16);public void append(ConfigMemento memento) {mementoList.add(memento);mementoMap.put(memento.getConfigFile().getVersionNo(), memento);cursorIdx++;}public ConfigMemento undo() {if (--cursorIdx <= 0) {return mementoList.get(0);}return mementoList.get(cursorIdx);}public ConfigMemento redo() {if (++cursorIdx > mementoList.size()) {return mementoList.get(mementoList.size() - 1);}return mementoList.get(cursorIdx);}public ConfigMemento get(String versionNo) {return mementoMap.get(versionNo);}
}
  • 这个类中主要实现的核心功能就是记录配置文件信息,也就是备忘录的效果,之后提供可以回滚和获取的方法,拿到备忘录的具体内容。
  • 同时这里设置了两个数据结构来存放备忘录,实际使用中可以按需设置。List<ConfigMemento>Map<String, ConfigMemento>
  • 最后是提供的备忘录操作方法。
    • 存放 append()、回滚 undo()、返回 redo()、定向获取 get(String versionNo)

3.4 单元测试

ApiTest.java

package com.lino.design.test;import com.alibaba.fastjson.JSON;
import com.lino.design.Admin;
import com.lino.design.ConfigFile;
import com.lino.design.ConfigOriginator;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Date;/*** @description: 单元测试*/
public class ApiTest {private Logger logger = LoggerFactory.getLogger(ApiTest.class);@Testpublic void test() {Admin admin = new Admin();ConfigOriginator configOriginator = new ConfigOriginator();configOriginator.setConfigFile(new ConfigFile("100001", "配置内容A=哈哈", new Date(), "小零哥"));admin.append(configOriginator.saveMemento());configOriginator.setConfigFile(new ConfigFile("100002", "配置内容A=嘻嘻", new Date(), "小零哥"));admin.append(configOriginator.saveMemento());configOriginator.setConfigFile(new ConfigFile("100003", "配置内容A=默默", new Date(), "小零哥"));admin.append(configOriginator.saveMemento());configOriginator.setConfigFile(new ConfigFile("100004", "配置内容A=嘿嘿", new Date(), "小零哥"));admin.append(configOriginator.saveMemento());// 历史配置(回滚)configOriginator.getMemento(admin.undo());logger.info("历史配置(回滚)undo:{}", JSON.toJSONString(configOriginator.getConfigFile()));// 历史配置(回滚)configOriginator.getMemento(admin.undo());logger.info("历史配置(回滚)undo:{}", JSON.toJSONString(configOriginator.getConfigFile()));// 历史配置(前进)configOriginator.getMemento(admin.redo());logger.info("历史配置(前进)redo:{}", JSON.toJSONString(configOriginator.getConfigFile()));// 历史配置(获取)configOriginator.getMemento(admin.get("100002"));logger.info("历史配置(获取)get:{}", JSON.toJSONString(configOriginator.getConfigFile()));}
}
  • 这里包括了四次信息存储和备忘录历史配置操作。
  • 通过上面添加了四次配置后,下面分别进行操作是:
    • 回滚1次再回滚1次之后向前进1次最后是获取指定的版本配置

测试结果

17:04:48.903 [main] INFO  com.lino.design.test.ApiTest - 历史配置(回滚)undo:{"content":"配置内容A=嘿嘿","dateTime":1675415088777,"operator":"小零哥","versionNo":"100004"}
17:04:48.913 [main] INFO  com.lino.design.test.ApiTest - 历史配置(回滚)undo:{"content":"配置内容A=默默","dateTime":1675415088777,"operator":"小零哥","versionNo":"100003"}
17:04:48.913 [main] INFO  com.lino.design.test.ApiTest - 历史配置(前进)redo:{"content":"配置内容A=嘿嘿","dateTime":1675415088777,"operator":"小零哥","versionNo":"100004"}
17:04:48.913 [main] INFO  com.lino.design.test.ApiTest - 历史配置(获取)get:{"content":"配置内容A=嘻嘻","dateTime":1675415088777,"operator":"小零哥","versionNo":"100002"}
  • 从测试结果效果上可以看到,历史配置按照我们的指令进行了回滚和前进,以及最终通过指定的版本进行获取,符合预期结果。

四、总结:备忘录模式

  • 备忘录模式可以满足在不破坏原有属性类的基础上,扩充了备忘录的功能。
  • 在以上的实现中我们将配置模拟存放到内存中,如果关机了会导致配置信息丢失,因为在一些真实的场景里还是需要存放到数据中。
    • 此种存放到内存中进行回复的场景也不是没有,比如:Photoshop、运营人员操作 ERP 配置活动。也就是即时性的一般不需要存放到库中进行恢复。
    • 另外如果是使用内存方式存放备忘录,需要考虑存储问题,避免造成内存大量消耗。

相关文章:

Java设计模式:四、行为型模式-05:备忘录模式

文章目录 一、定义&#xff1a;备忘录模式二、模拟场景&#xff1a;备忘录模式三、改善代码&#xff1a;备忘录模式3.1 工程结构3.2 备忘录模式模型结构图3.3 备忘录模式定义3.3.1 配置信息类3.3.2 备忘录类3.3.3 记录者类3.3.4 管理员类 3.4 单元测试 四、总结&#xff1a;备忘…...

MongoDB实验——MongoDB配置用户的访问控制

MongoDB 配置用户的访问控制 一、 实验原理 理解admin数据库&#xff1a;安装MongoDB时&#xff0c;会自动创建admin数据库&#xff0c;这是一个特殊数据库&#xff0c;提供了普通数据库没有的功能&#xff0c;例如&#xff0c;有些账户角色赋予用户操作多个数据库的权限&…...

golang逃逸技术分析

“ 申请到栈内存好处&#xff1a;函数返回直接释放&#xff0c;不会引起垃圾回收&#xff0c;对性能没有影响。 申请到堆上面的内存才会引起垃圾回收。 func F() { a : make([]int, 0, 20) b : make([]int, 0, 20000) l : 20 c : make([]int, 0, l)} “ a和b代码一样&#xff0…...

说说你了解的 Nginx

分析&回答 nginx性能数据 高并发连接: 官方称单节点支持5万并发连接数&#xff0c;实际生产环境能够承受2-3万并发。内存消耗少: 在3万并发连接下&#xff0c;开启10个nginx进程仅消耗150M内存 (15M10150M) 1. 正向、反向代理 所谓“代理”&#xff0c;是指在内网边缘 …...

SpringWeb(SpringMVC)

目录 SpringWeb介绍 搭建 SpringWeb SpringWeb介绍 Spring Web是一个基于 Servlet API 构建的原始 web 框架&#xff0c;用于构建基于MVC模式的Web应用程序。在 web 层框架历经 Strust1&#xff0c;WebWork&#xff0c;Strust2 等诸多产品的历代更选 之后&#xff0c;目前业界普…...

Mysql 语句

数据库管理 SQL语言分类 DDL 数据定义语言&#xff0c;用于创建数据库对象&#xff0c;如库、表、索引等 create 创建 create database/table; 数据库/表 create table 表名 &#xff08;括号内添加类型和字段&#xff09;;drop 删除 drop database/table; 数据库/表…...

软考高级架构师——6、软件架构设计

像学写文章一样&#xff0c;在学会字、词、句之后&#xff0c;就应上升到段落&#xff0c;就应追求文章的“布局谋 篇”&#xff0c;这就是架构。通俗地讲&#xff0c;软件架构设计就是软件系统的“布局谋篇”。 人们在软件工程实践中&#xff0c;逐步认识到了软件架构的重要性…...

虚拟内存相关笔记

虚拟内存是计算机系统内存管理的一个功能&#xff0c;它允许程序认为它们有比实际物理内存更多的可用内存。它使用硬盘来模拟额外的RAM。当物理内存不足时&#xff0c;操作系统将利用磁盘空间作为虚拟内存来存储数据。这种机制提高了资源的利用率并允许更大、更复杂的应用程序的…...

【linux】定时任务讲解

文章目录 一. 在某时刻只执行一次&#xff1a;at1. 设置定时任务2. 查看和删除定时任务 二. 周期性执行任务&#xff1a;cron1. 启动crond进程2. 编辑定时任务3. 查看和删除4. 用户权限4.1. 黑名单4.2指定用户 三. /etc/crontab的管理 一. 在某时刻只执行一次&#xff1a;at 1…...

安卓10创建文件夹失败

最近在做拍照录像功能&#xff0c;已经有了文件读写权限&#xff0c;却发现在9.0手机上正常使用&#xff0c;但是在安卓12系统上根本没有创建文件夹。经过研究发现&#xff0c;创建名称为“DCIM”的文件夹可以&#xff0c;别的又都不行。而且是getExternalStorageDirectory和ge…...

文件操作(c/c++)

文件操作可以概括为几步&#xff1a; 打开文件&#xff0c;写入文件&#xff0c;读取文件&#xff0c;关闭文件 FILE FILE 是一个在C语言中用于文件操作的库函数&#xff0c;它提供了一系列函数来实现文件的创建、打开、读取、写入、关闭等操作。FILE 库函数可以帮助开发者处理…...

设计模式-适配器

文章目录 一、简介二、适配器模式基础1. 适配器模式定义与分类2. 适配器模式的作用与优势3.UML图 三、适配器模式实现方式1. 类适配器模式2. 对象适配器模式3.类适配器模式和对象适配器模式对比 四、适配器模式应用场景1. 继承与接口的适配2. 跨平台适配 五、适配器模式与其他设…...

C. Queries for the Array - 思维

分析&#xff1a; 分析出现矛盾的地方&#xff0c;也就是可能遇到0&#xff0c;并且已有字符串的长度小于等于1&#xff0c;另一种情况就是&#xff0c;遇到了1并且已有字符串不是排好序的&#xff0c;或者遇到了0已有字符串是排好序的&#xff0c;那么可以遍历字符串&#xff…...

音频——硬件拓扑

文章目录 硬件拓扑I2S 数据通路五线模式四线模式两线 TX两线 RX 典型应用硬件连接数据流 硬件拓扑 控制路径&#xff1a;UART/I2C/SPI数据路径&#xff1a;I2S 简略图如下 I2S 数据通路 五线模式 四线模式 两线 TX 两线 RX 典型应用 硬件连接 控制信号&#xff1a;SPI 用…...

Oracle表索引查看方法总结(查看oracle表索引)

Oracle表索引查看方法总结 Oracle是当前应用最广泛的关系数据库&#xff0c;也是多数大型企业使用的数据库。Oracle表索引在提高查询效率方面起着至关重要的作用&#xff0c;掌握该方法也是技术人员必备技能之一。本文总结了几种常见的查看Oracle表索引信息的方法&#xff0c;…...

react css 污染解决方法

上代码 .m-nav-bar {background: #171a21;.content {height: 104px;margin: 0px auto;} }import React from "react"; import styles from ./css.module.scssexport default class NavBar extends React.Component<any, any> {constructor (props: any) {supe…...

volatile 关键字 与 CPU cache line 的效率问题

分析&回答 Cache Line可以简单的理解为CPU Cache中的最小缓存单位。目前主流的CPU Cache的Cache Line大小都是64Bytes。假设我们有一个512字节的一级缓存&#xff0c;那么按照64B的缓存单位大小来算&#xff0c;这个一级缓存所能存放的缓存个数就是512/64 8个。具体参见下…...

又一关键系统上线,理想车云和自动驾驶系统登陆OceanBase

8 月 1 日&#xff0c;理想汽车公布 7 月交付数据&#xff0c;理想汽车 2023 年 7 月共交付新车 34,134 辆&#xff0c;同比增长 227.5%&#xff0c;并已连续两个月交付量突破三万。至此&#xff0c;理想汽车 2023 年累计交付量已经达到 173,251 辆&#xff0c;远超 2022 年全年…...

SIEM(安全信息和事件管理)解决方案

什么是SIEM 安全信息和事件管理&#xff08;SIEM&#xff09;是一种可帮助组织在安全威胁危害到业务运营之前检测、分析和响应安全威胁的解决方案&#xff0c;将安全信息管理 (SIM) 和安全事件管理 (SEM) 结合到一个安全管理系统中。SIEM 技术从广泛来源收集事件日志数据&…...

Go 自学:map关联数组

以下代码展示了如何建立一个map。 我们可以使用delete删除map中的元素。 我们还可以使用loop遍历map中的所有元素。 package mainimport ("fmt" )func main() {languages : make(map[string]string)languages["JS"] "Javascript"languages[&qu…...

AIGlasses_for_navigation基础教程:无需ESP32,纯Web端完成所有功能验证

AIGlasses_for_navigation基础教程&#xff1a;无需ESP32&#xff0c;纯Web端完成所有功能验证 1. 引言&#xff1a;从零开始&#xff0c;验证你的智能眼镜导航系统 你是不是也对那个集成了AI、传感器和导航功能的智能眼镜项目——AIGlasses_for_navigation——感到好奇&…...

OpenClaw隐私保护:QwQ-32B本地化部署数据边界控制

OpenClaw隐私保护&#xff1a;QwQ-32B本地化部署数据边界控制 1. 为什么需要关注OpenClaw的数据边界 去年我在帮一个法律团队搭建自动化文档处理系统时&#xff0c;第一次深刻意识到数据边界的重要性。他们处理的案件材料包含大量敏感信息&#xff0c;任何数据泄露都可能造成…...

ComfyUI IPAdapter Plus插件ClipVision模型加载故障排除指南

ComfyUI IPAdapter Plus插件ClipVision模型加载故障排除指南 【免费下载链接】ComfyUI_IPAdapter_plus 项目地址: https://gitcode.com/gh_mirrors/co/ComfyUI_IPAdapter_plus 问题诊断&#xff1a;ClipVision模型加载失败的典型症状与成因分析 在ComfyUI工作流中集成…...

Unity游戏开发实战:用三阶贝塞尔曲线为你的角色设计一条丝滑的移动路径

Unity游戏开发实战&#xff1a;用三阶贝塞尔曲线为你的角色设计一条丝滑的移动路径 在游戏开发中&#xff0c;角色的移动路径设计往往决定了玩家的第一印象。想象一下&#xff0c;当你的主角从一个平台跳跃到另一个平台时&#xff0c;是希望看到机械的直线移动&#xff0c;还是…...

CasRel关系抽取实战:对接Airflow构建SPO抽取ETL调度流水线

CasRel关系抽取实战&#xff1a;对接Airflow构建SPO抽取ETL调度流水线 1. 项目背景与价值 在日常业务中&#xff0c;我们经常需要从大量文本数据中提取结构化信息。比如从新闻文章中提取人物关系&#xff0c;从产品描述中提取规格参数&#xff0c;从客服对话中提取用户诉求等…...

天硕(TOPSSD)深度解析:存储介质分类视角下,SSD固态硬盘如何一步步演进?

在信息技术持续迭代的背景下&#xff0c;存储介质的选择已不再局限于容量与成本&#xff0c;而逐渐成为决定系统性能上限、响应延迟与长期稳定性的关键因素。从光学存储到机械硬盘&#xff08;HDD&#xff09;&#xff0c;再到以半导体技术为核心的SSD固态硬盘&#xff0c;每一…...

Asian Beauty Z-Image Turbo惊艳案例:单卡RTX4090每秒1.8帧的Turbo实时生成

Asian Beauty Z-Image Turbo惊艳案例&#xff1a;单卡RTX4090每秒1.8帧的Turbo实时生成 东方美学图像生成的本地高效解决方案 在数字内容创作蓬勃发展的今天&#xff0c;高质量人像图像生成需求日益增长&#xff0c;特别是具有东方美学特色的图像。传统云端生成方案虽然方便&am…...

Win10 LTSC 1809系统下Docker 4.0.0与CVAT 2.31.0的完美搭配:避坑指南与性能优化

Win10 LTSC 1809系统下Docker 4.0.0与CVAT 2.31.0的完美搭配&#xff1a;避坑指南与性能优化 在工业级计算机视觉标注领域&#xff0c;CVAT&#xff08;Computer Vision Annotation Tool&#xff09;凭借其开源特性和强大的标注功能&#xff0c;已成为许多研究团队的首选工具。…...

OWL ADVENTURE Java面试题实战:手写一个简单的图像加载器

OWL ADVENTURE Java面试题实战&#xff1a;手写一个简单的图像加载器 最近在准备Java面试的朋友&#xff0c;是不是经常被问到IO、多线程这些基础&#xff1f;光背八股文总觉得心里没底。今天咱们换个玩法&#xff0c;不搞虚的&#xff0c;直接动手写一个能用在真实项目里的东…...

Anthropic提示工程教程:从入门到精通的完整指南

Anthropic提示工程教程&#xff1a;从入门到精通的完整指南 【免费下载链接】prompt-eng-interactive-tutorial Anthropics Interactive Prompt Engineering Tutorial 项目地址: https://gitcode.com/GitHub_Trending/pr/prompt-eng-interactive-tutorial Anthropic的交…...