笨蛋学设计模式行为型模式-备忘录模式【22】

行为型模式-备忘录模式

    • 8.9备忘录模式
      • 8.9.1概念
      • 8.9.2场景
      • 8.9.3优势 / 劣势
      • 8.9.4备忘录模式可分为
      • 8.9.5备忘录模式
      • 8.9.6实战
        • 8.9.6.1题目描述
        • 8.9.6.2输入描述
        • 8.9.6.3输出描述
        • 8.9.6.4代码
      • 8.9.7总结

8.9备忘录模式

8.9.1概念

​ 备忘录模式允许在不暴露对象实现细节的情况下捕获和恢复对象的内部状态。通过将对象的状态封装在备忘录对象中,并将备忘录对象保存在一个管理者对象中,可以在需要时回滚到对象之前的状态。

8.9.2场景

​ 在现代办公场景中,备忘录模式可以应用于文档编辑工具中。以Office工具为例,当用户在云文档中进行编辑时,系统会自动将当前的文档内容保存在一个备忘录对象中,并将备忘录对象存储在云端的服务器上。每隔一段时间,系统会判断是否需要保存文档的状态,如果需要,则将当前的备忘录对象保存为一个快照,以便日后恢复文档的状态。

8.9.3优势 / 劣势

  • 提供恢复机制:当用户有需要时,能够比较方便地将数据恢复到某个历史的状态
  • 实现内部封装:除了创建它的发起人之外,其他对象都不能够访问这些状态信息

  • 资源消耗大:若需要保存的内部状态信息过多或者特别频繁是,将会占用比较大的内存资源
  • 难以确定保存时间:当对象的状态发生改变时,需要判断是否需要存储备忘录

8.9.4备忘录模式可分为

  • 发起人Originator:需要还原状态的那个对象,负责创建一个备忘录,并使用备忘录记录当前时刻的内部状态
  • 备忘录Memento:存储发起人对象的内部状态,它可以包含发起人的部分或全部状态信息,但是对外部是不可见的,只有发起人能够访问备忘录对象的状态

备忘录有两个接口,发起人能够通过宽接口访问数据,管理者只能看到窄接口,并将备忘录传递给其他对象

  • 管理者Caretaker:负责存储备忘录对象,但并不了解其内部结构,管理者可以存储多个备忘录对象
  • 客户端:在需要恢复状态时,客户端可以从管理者哪里获取备忘录对象,并将其传递给发起人进行状态的恢复

8.9.5备忘录模式

package com.technologystatck.designpattern.mode.memorandum;import java.util.ArrayList;
import java.util.List;public class Memorandum {public static void main(String[] args) {//创建发起人对象Originator originator = new Originator();originator.setState("State 1");//创建管理者对象Caretaker caretaker = new Caretaker();//保存当前状态caretaker.addMemento(originator.createMemento());System.out.println("Current State:"+originator.getState());//修改状态originator.setState("State 2");System.out.println("Current State:"+originator.getState());//再次保存当前状态caretaker.addMemento(originator.createMemento());//恢复到先前状态originator.restoreFromMemento(caretaker.getMemento(0));System.out.println("Current State:"+originator.getState());}
}//创建发起人类:可以创建备忘录对象
class Originator{//备忘录的状态private String state;public void setState(String state){this.state=state;}public String getState(){return state;}//创建备忘录对象public Memento createMemento(){return new Memento(this.state);}//通过备忘录对象恢复状态public void restoreFromMemento(Memento memento){state=memento.getState();}
}//创建备忘录类:保存发起人对象的状态
class Memento{private String state;//保存发起人的状态public Memento(String state){this.state=state;}public String getState(){return state;}
}//创建备忘录管理者类:保存备忘录对象
class Caretaker{private List<Memento> mementos=new ArrayList<>();//添加备忘录对象public void addMemento(Memento memento){mementos.add(memento);}//获取备忘录对象public Memento getMemento(int index){return mementos.get(index);}
}

8.9.6实战

8.9.6.1题目描述

小明正在设计一个简单的计数器应用,支持增加(Increment)和减少(Decrement)操作,以及撤销(Undo)和重做(Redo)操作,请你使用备忘录模式帮他实现。

8.9.6.2输入描述

输入包含若干行,每行包含一个字符串,表示计数器应用的操作,操作包括 “Increment”、“Decrement”、“Undo” 和 “Redo”。

8.9.6.3输出描述

对于每个 “Increment” 和 “Decrement” 操作,输出当前计数器的值,计数器数值从0开始 对于每个 “Undo” 操作,输出撤销后的计数器值。 对于每个 “Redo” 操作,输出重做后的计数器值。

8.9.6.4代码
package com.technologystatck.designpattern.mode.memorandum;import java.util.Scanner;
import java.util.Stack;public class Test {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);Counter counter = new Counter();//处理计数器应用的输入while (scanner.hasNext()) {String operation = scanner.next();switch (operation) {case "Increment":counter.increment();break;case "Decrement":counter.decrement();break;case "Undo":counter.undo();break;case "Redo":counter.redo();break;}System.out.println(counter.getValue());}}
}//备忘录
class Memento {//备忘录的状态private int value;public Memento(int value) {this.value = value;}public int getValue() {return value;}}//创建人
class Counter {//表示计数器的值private int value;//撤销操作private Stack<Memento> undoStack = new Stack<>();//重做操作private Stack<Memento> redoStack = new Stack<>();//减少计数器的值public void increment() {//执行撤销操作时,需要清除一些无效的备忘录对象//这些备忘录对象失去作用了需要清空redoStack.clear();//需要将当前状态保存在撤销栈中undoStack.push(new Memento(value));//计数器的值加1value++;}//增加计数器值public void decrement() {//执行重做操作时,需要清除一些无效的备忘录对象//这些备忘录对象失去作用了需要清空redoStack.clear();//需要将当前状态保存在撤销栈中undoStack.push(new Memento(value));//计数器的值加1value--;}/*** 当执行撤销或重做的操作时,都会将相关的备忘录对象* 移动到另一个栈中,保证了操作的一致性*///撤销操作public void undo() {//若撤销栈不为空,则将当前栈顶元素移动到重做栈中,//并将当前栈顶元素的值赋给value变量if (!undoStack.isEmpty()) {redoStack.push(new Memento(value));value = undoStack.pop().getValue();}}//重做操作public void redo() {//若重做栈不为空,则将当前栈顶元素移动到撤销栈中//并将当前栈顶元素的值赋给value变量if (!redoStack.isEmpty()) {undoStack.push(new Memento(value));value = redoStack.pop().getValue();}}//获取value值public int getValue() {return value;}
}

8.9.7总结

  • 优点:简化了原始对象的代码结构,支持撤销和恢复操作
  • 总结:将对象的状态使用栈或集合的形式保存起来,当需要撤销或重做时,就记录当前对象的状态,并将栈或集合中的值取出来
  • 场景:适用于需要保证对象内部状态的封装和私有性前提下可以轻松地添加新的备忘录和发起人以此来实现备份

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

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

相关文章

140 反装链表

问题描述&#xff1a;给你单链表的头指针和两个整数left和right&#xff0c;其中left<right.请你反转从位置left到right位置的链表节点&#xff0c;返回反转后的链表。三指针求解&#xff1a;首先定义一个指针指向反转链表前的那一个位置pre&#xff0c;然后找到反转链表最后…

第6章 SpringBoot缓存管理

学习目标 了解SpringBoot的默认缓存 熟悉SpringBoot中Redis的缓存机制及实现 掌握SpringBoot整合Redis的缓存实现 缓存是分布式系统中的重要组件&#xff0c;主要解决数据库数据的高并发访问问题。在实际开发中&#xff0c;尤其是用户访问量较大的网站&#xff0c;为了提高服…

js实现走马灯效果

走马灯效果通常指的是一种文本或图片在页面上循环滚动的效果。在JavaScript中&#xff0c;我们可以使用定时器&#xff08;如 setInterval&#xff09;来实现这种效果。以下是一个简单的示例&#xff0c;展示了如何使用JavaScript和CSS实现走马灯效果&#xff1a; 1.HTML 结构…

HarmonyOS SDK,助力开发者打造焕然一新的鸿蒙原生应用

鸿蒙生态千帆启航仪式于1月18日正式启动。从2019年HarmonyOS正式发布到2020年“没有人能够熄灭漫天星光”&#xff0c;今天&#xff0c;满天星光终汇成璀璨星河&#xff0c;HarmonyOS NEXT鸿蒙星河版重磅发布&#xff0c;带来了全新架构、全新体验、全新生态。作为支撑鸿蒙原生…

Spring--@Async解析

一、Async 简介 从Spring3开始提供了Async注解&#xff0c;被该注解标注的方法&#xff0c;Spring底层会新建一个线程池或者使用已有的线程池中的线程去异步的执行被标注的方法。 二、Async 工作原理 Async与Transactional 工作原理基本是一样的&#xff0c;也是通过Spring …

100天精通鸿蒙从入门到跳槽——第11天:TypeScript 知识储备:装饰器

博主猫头虎的技术世界 &#x1f31f; 欢迎来到猫头虎的博客 — 探索技术的无限可能&#xff01; 专栏链接&#xff1a; &#x1f517; 精选专栏&#xff1a; 《面试题大全》 — 面试准备的宝典&#xff01;《IDEA开发秘籍》 — 提升你的IDEA技能&#xff01;《100天精通Golang》…

代码随想录 Leetcode150. 逆波兰表达式求值

题目&#xff1a; 代码(首刷看解析 2024年1月21日&#xff09;&#xff1a; class Solution { public:int evalRPN(vector<string>& tokens) {stack<long long> st; for (int i 0; i < tokens.size(); i) {if (tokens[i] "" || tokens[i] &qu…

AP5191 降压恒流 双灯 12V5A 一切一LED车灯汽车大灯驱动方案

AP5191是一款PWM工作模式,高效率、外围简 单、内置功率MOS管&#xff0c;适用于4.5-150V输入的高 精度降压LED恒流驱动芯片。输出功率150W&#xff0c; 电流6A。 AP5191可实现线性调光和PWM调光&#xff0c;线性调 光脚有效电压范围0.55-2.6V. AP5191 工作频率可以通过RT 外部…

咱们的打造自己的赚钱机器之打造自己的特色网站系列连续博文开始发布了

打造自己的赚钱机器之打造自己的特色网站前言1 咱们从今天开始正式连载咱们的打造个人特色网站系列博文. 整个博文实际上就是一本书,只是还未写出来.我就先以博文的形式发布,最后整理修改,再编撰成册. 那么,<<打造自己的特色网站>>系列博文为什么值得一看,又有哪…

win 下使用 cmd 运行 jar 包

1、使用 Win R 输入 cmd 命令打开命令提示符 2、在 cmd 窗口中输入以下命令 java -jar xxxxxx.jar 运行 jar 包&#xff0c;控制台出现中文乱码 原因是 windows 默认使用 GBK 编码格式&#xff0c;程序使用 UTF-8 编码格式 将编码格式改为 UTF-8 编码&#xff0c;在 cmd 窗…

JavaScript库jquery的使用方法

"写更少&#xff0c;做更多"是jquery的设计理念&#xff0c;jquery是一个兼容多浏览器的JavaScript库&#xff0c;利用jquery的语法设计能使开发更便捷。 网页添加jquery的方法:1.从jquery.com下载库&#xff1b;2.从CDN中载入库&#xff08;示例使用&#xff09;&a…

pytorch模型转caffe模型

记录一个好用的pytorch模型转caffe模型的方法&#xff0c;源码链接如下&#xff1a; https://github.com/xxradon/PytorchToCaffe 把代码clone下来后&#xff0c;进入example目录便可查看示例&#xff0c; cd example python resnet_pytorch_2_caffe.py import sys sys.pat…

【遥感数字图像处理(朱文泉)】各章博文链接汇总及思维导图

遥感数字图像处理课程汇总 第0章 绪论第一章 数字图像基础第二章 数字图像存储与处理第三章 空间域处理方法第四章 变换域处理方法第五章 辐射校正第六章 几何校正第七章 图像去噪声第八章 图像增强第九章 感兴趣目标及对象提取第十章 特征提取与选择第十一章 遥感数字图像分类…

【ASP.NET Core 基础知识】--路由和请求处理--路由概念(二)

一、路由参数传递方式 1.1 查询字符串参数 在路由中&#xff0c;查询字符串参数是一种常见的方式传递信息。这种方式通过URL中的查询字符串&#xff08;?key1value1&key2value2&#xff09;将参数附加到请求中。在ASP.NET Core中&#xff0c;可以通过以下方式在控制器动…

c++学习之IO流

目录 前言&#xff1a; 一&#xff0c;流的概念 二&#xff0c;c的io流 输入输出流 缓冲区的同步 文件流 文件的打开 文件读写自定义类型数据 字符流 1. 将数值类型数据格式化为字符串 2. 字符串拼接 3. 序列化和反序列化结构数据 前言&#xff1a; 在了解c的输入输…

SpringBoot异常处理和单元测试

学习目标 Spring Boot 异常处理Spring Boot 单元测试 1.SpringBoot异常处理 1.1.自定义错误页面 SpringBoot默认的处理异常的机制&#xff1a;SpringBoot 默认的已经提供了一套处理异常的机制。一旦程序中出现了异常 SpringBoot 会向/error 的 url 发送请求。在 springBoot…

c语言->学会offsetof宏计算结构体相对偏移量

前言 ✅作者简介&#xff1a;大家好&#xff0c;我是橘橙黄又青&#xff0c;一个想要与大家共同进步的男人&#x1f609;&#x1f609; &#x1f34e;个人主页&#xff1a;橘橙黄又青-CSDN博客 目的&#xff0c;学习offsetof宏计算结构体相对偏移量 1.offsetof宏 来我们看图…

vector讲解

在学习玩string后我们开始学习vector&#xff0c;本篇博客将对vector进行简单的介绍&#xff0c;还会对vector一些常用的函数进行讲解 vector的介绍 实际上vector就是一个数组的数据结构&#xff0c;但是vector是由C编写而成的&#xff0c;他和数组也有本质上的区别&#xff…

2.机器学习-K最近邻(k-Nearest Neighbor,KNN)分类算法原理讲解

2️⃣机器学习-K最近邻&#xff08;k-Nearest Neighbor&#xff0c;KNN&#xff09;分类算法原理讲解 个人简介一算法概述二算法思想2.1 KNN的优缺点 三实例演示3.1电影分类3.2使用KNN算法预测 鸢(yuan)尾花 的种类3.3 预测年收入是否大于50K美元 个人简介 &#x1f3d8;️&…

android 导航app 稳定性问题总结

一 重写全局异常处理&#xff1a; 1 是过滤掉一些已知的无法处理的 问题&#xff0c;比如TimeoutException 这种无法根除只能缓解的问题可以直接catch掉 2 是 一些无法继续的问题可以直接杀死重启&#xff0c;一些影响不是很大的&#xff0c;可以局部还原 比如&#xff1a; p…