Java设计模式—备忘录模式(快照模式)

定义 

        备忘录模式提供了一种状态恢复的实现机制,使得用户可以方便地回到一个特定的历史步骤,当新的状态无效或者存在问题时,可以使用暂时存储起来的备忘录将状态复原,很多软件都提供了撤销(Undo)操作,如 Word、记事本、Photoshop、IDEA等软件在编辑时按 Ctrl+Z 组合键时能撤销当前操作,使文档恢复到之前的状态;还有在 浏览器 中的后退键、数据库事务管理中的回滚操作、玩游戏时的中间结果存档功能、数据库与操作系统的备份操作、棋类游戏中的悔棋功能等都属于这类。  

组成结构

备忘录模式的主要角色如下:

发起人(Originator)角色:

记录当前时刻的内部状态信息,提供创建备忘录和恢复备忘录数据的功能,实现其他业务功能,它可以访问备忘录里的所有信息。

备忘录(Memento)角色:

负责存储发起人的内部状态,在需要的时候提供这些内部状态给发起人。

管理者(Caretaker)角色:

对备忘录进行管理,提供保存与获取备忘录的功能,但其不能对备忘录的内容进行访问与修改。

备忘录有两个等效的接口:

窄接口:管理者(Caretaker)对象(和其他发起人对象之外的任何对象)看到的是备忘录的窄接口(narror Interface),这个窄接口只允许他把备忘录对象传给其他的对象。
宽接口:与管理者看到的窄接口相反,发起人对象可以看到一个宽接口(wide Interface),这个宽接口允许它读取所有的数据,以便根据这些数据恢复这个发起人对象的内部状态。

package debug01;

public class debug01 {
    public static void main(String[] args) {
        Originator originator = new Originator();
        CareTaker careTaker = new CareTaker();
        originator.setState("State #1");
        originator.setState("State #2");
        careTaker.add(originator.saveStateToMemento());
        originator.setState("State #3");
        careTaker.add(originator.saveStateToMemento());
        originator.setState("State #4");
        System.out.println("Current State: " + originator.getState());
        originator.getStateFromMemento(careTaker.get(0));
        System.out.println("First saved State: " + originator.getState());
        originator.getStateFromMemento(careTaker.get(1));
        System.out.println("Second saved State: " + originator.getState());
    }
}
  • debug01 类是程序的入口点,其中包含 main 方法。
  • 在 main 方法中,首先创建了 Originator 和 CareTaker 的实例。
  • 然后,originator 对象的状态被设置为 "State #1"、"State #2"、"State #3" 和 "State #4",并且在每次状态更改后,将当前状态保存到 careTaker 中。
  • 最后,打印出最后设置的状态以及通过 careTaker 恢复的两个先前保存的状态。
package debug01;

import java.util.*;

public class CareTaker {
    private List<Memento> mementoList = new ArrayList<Memento>();

    public void add(Memento state) {
        mementoList.add(state);
    }

    public Memento get(int index) {
        return mementoList.get(index);
    }
}
  • CareTaker 类负责保存 Originator 的状态。它使用一个 List 来存储 Memento 对象。
  • add 方法用于向 mementoList 中添加状态。
  • get 方法用于获取指定索引位置的 Memento 对象。
package debug01;

public class Originator {
    private String state;

    public void setState(String state) {
        this.state = state;
    }

    public String getState() {
        return state;
    }

    public Memento saveStateToMemento() {
        return new Memento(state);
    }

    public void getStateFromMemento(Memento memento) {
        state = memento.getState();
    }
}
  • Originator 类是原始对象,其中包含了要保存的状态。
  • setState 方法用于设置状态。
  • getState 方法用于获取状态。
  • saveStateToMemento 方法创建并返回一个新的 Memento 对象,该对象包含了当前状态的副本。
  • getStateFromMemento 方法用于从 Memento 对象中恢复状态。

package debug01;
public class Memento {
    private String state;
    public Memento(String state) {
        this.state = state;
    }
    public String getState() {
        return state;
    }
}
  • Memento 类用于存储 Originator 的状态。
  • 它有一个带有状态参数的构造函数,用于初始化状态。
  • getState 方法用于获取状态的值。

整个代码实现了备忘录模式,用于保存和恢复对象的状态。

优缺点

优点:

- 提供了一种可以恢复状态的机制。当用户需要时能够比较方便地将数据恢复到某个历史的状态。
- 实现了内部状态的封装。除了创建它的发起人之外,其他对象都不能够访问这些状态信息。
- 简化了发起人类。发起人不需要管理和保存其内部状态的各个备份,所有状态信息都保存在备忘录中,并由管理者进行管理,这符合单一职责原则。

缺点:

- 资源消耗大。如果要保存的内部状态信息过多或者特别频繁,将会占用比较大的内存资源。

使用场景

- 需要保存与恢复数据的场景,如玩游戏时的中间结果的存档功能。
- 需要提供一个可回滚操作的场景,如 Word、记事本、Photoshop,idea等软件在编辑时按 Ctrl+Z 组合键,还有数据库中事务操作。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

白酒:浓香型白酒的典型代表与特点

云仓酒庄的豪迈白酒作为白酒的品牌&#xff0c;具有一系列与众不同的特点和优势。下面云仓酒庄的豪迈白酒将从典型性、品质、口感和包装等方面深入分析白酒的特点&#xff0c;以及它如何体现浓香型白酒的魅力。 浓香型白酒是中国白酒的重要分支&#xff0c;以浓郁的香味和与众不…

设计模式之原型模式讲解

原型模式本身就是一种很简单的模式&#xff0c;在Java当中&#xff0c;由于内置了Cloneable 接口&#xff0c;就使得原型模式在Java中的实现变得非常简单。UML图如下&#xff1a; 我们来举一个生成新员工的例子来帮助大家理解。 import java.util.Date; public class Employee…

SI案例分享--冷却液对PCIe链路性能的影响

目录 0 引言 1 PCIe线缆组件在不同冷却方式中的性能对比 1.1 配置Paddle card互连的电缆组件测试结果&#xff08;cable-1&#xff09; 1.2 直接焊接互连的电缆组件测试结果&#xff08;cable-2&#xff09; 1.3 一侧配置Paddle card、一侧直接焊接互连的电缆组件测试结果…

阿里云账号怎么注册?看这一篇就够了

阿里云账号怎么注册&#xff1f;阿里云账号支持手机号注册、阿里云APP注册、淘宝、支付宝和钉钉多种注册方式&#xff0c;账号注册后需要通过实名认证才可以购买或使用云产品&#xff0c;使用淘宝、支付宝或钉钉注册方式可以免去实名认证步骤&#xff0c;阿里云百科aliyunbaike…

深入解析MD5哈希算法:原理、应用与安全性

码到三十五 &#xff1a; 个人主页 心中有诗画&#xff0c;指尖舞代码&#xff0c;目光览世界&#xff0c;步履越千山&#xff0c;人间尽值得 ! 本文将深入探讨MD5哈希算法的工作原理、应用场景以及安全性问题。我们将了解MD5如何生成固定长度的哈希值&#xff0c;以及它在数…

Leo赠书活动-21期 《一篇讲明白 Hadoop 生态的三大部件》

✅作者简介&#xff1a;大家好&#xff0c;我是Leo&#xff0c;热爱Java后端开发者&#xff0c;一个想要与大家共同进步的男人&#x1f609;&#x1f609; &#x1f34e;个人主页&#xff1a;Leo的博客 &#x1f49e;当前专栏&#xff1a; 赠书活动专栏 ✨特色专栏&#xff1a;…

【OpenAI援引马斯克评价中国】小米汽车 SU7 顶配版或超 30 万/OpenAI 加持机器人亮相/荣耀已投入 100 亿研发 AI

雷军&#xff1a;共建一个更良性包容的汽车市场舆论环境 Figure 与 OpenAI 联手推出新机器人 亚马逊和 Google 悄悄降低对生成式 AI 的预期 小米生态链模式大改革&#xff0c;将进行分级管理 掌阅科技&#xff1a;致力打造国内首款真正 AI 阅读应用 荣耀称已投入 100 亿用于 AI…

Ipython与Jupyter之间的关系

IPython 和 Jupyter 之间的关系可以从它们的历史和目标中得到很好的解释。IPython&#xff08;Interactive Python&#xff09;最初是由 Fernando Prez 于 2001 年创建的&#xff0c;旨在提升 Python 的交互式计算体验。它提供了一个强大的交互式 Python shell 和一个面向高效计…

C语言例4-27:计算1+2+...+100之和(利用while语句实现)。

代码如下&#xff1a; //计算12...100之和&#xff08;利用while语句实现&#xff09;。 #include<stdio.h> int main(void) {int n1, sum0;while(n<100){ //复合语句作为当型循环结构的循环体sumsumn;n;}printf("sum %d\n",sum);retu…

Phoenix伪分布安装

引言 Phoenix是构建在HBase上的一个SQL层&#xff0c;能让我们用标准的JDBC APIs而不是HBase客户端APIs来创建表&#xff0c;插入数据和对HBase数据进行查询。Phoenix完全使用Java编写&#xff0c;作为HBase内嵌的JDBC驱动。Phoenix查询引擎会将SQL查询转换为一个或多个HBase扫…

国赛大纲解读

1. 第一部分,是针对5G基础知识的掌握,第二部分是人工智能基本算法的掌握,就是人工智能的应用,用5G+人工智能(AI算法)进行网络优化的问题,要有网络优化的基础知识,比如说:某个区域的覆盖问题,覆盖特别差,但有数据,覆盖电频,srp值这些数据给你,根据数据来判断是…

Rabbitmq消息顺序的问题以及解决方案

1.1消息顺序的场景 场景1&#xff1a;一个queue&#xff0c;多个consumer 一个queue&#xff0c;有多个consumer去消费&#xff0c;这样就会造成顺序的错误&#xff0c;consumer从MQ里面读取数据是有序的&#xff0c;但是每个consumer的执行时间是不固定的&#xff0c;无法保…

1-28 核心类库(四)

一 BigDecimal类(会用) 1.作用:用来进行金融类项目中的数据的精确计算 2. import java.math.BigDecimal; import java.math.RoundingMode;public class BigDecimalTest {public static void main(String[] args) {//一定要字符串 int类型的答案不一定准BigDecimal bd1new B…

专题二_滑动窗口(1)

目录 209. 长度最小的子数组 解析 题解 3. 无重复字符的最长子串 解析 题解 1004. 最大连续1的个数 III 解析 题解 209. 长度最小的子数组 209. 长度最小的子数组 - 力扣&#xff08;LeetCode&#xff09; 解析 题解 class Solution { public:int minSubArrayLen(int…

JAVA WEB 能够实现整个文件夹的上传下载吗?

导入项目&#xff1a; 导入到Eclipse&#xff1a;导入项目 导入到IDEA&#xff1a;导入项目 springboot统一配置&#xff1a;springboot-配置 下载示例&#xff1a; https://gitee.com/xproer/up6-jsp-eclipse/tree/6.5.40/ 工程 NOSQL NOSQL示例不需要任何配置&#xff0c;可…

【Java程序员福音】国外Java 程序员开发常用的工具(全)

Java是一门开源语言&#xff0c;所以可以选择的开发环境很多&#xff0c;你适合哪一个呢&#xff1f;整理了一些Java程序员开发常用的工具&#xff0c;需要的同学可以收藏。 1、免费开源Eclipse Eclipse最初是由IBM公司开发的替代商业软件Visual Age for Java的下一代IDE开发环…

深入浅出:探索Hadoop生态系统的核心组件与技术架构

目录 前言 HDFS Yarn Hive HBase Spark及Spark Streaming 书本与课程推荐 关于作者&#xff1a; 推荐理由&#xff1a; 作者直播推荐&#xff1a; 前言 进入大数据阶段就意味着 进入NoSQL阶段&#xff0c;更多的是面向OLAP场景&#xff0c;即数据仓库、BI应用等。 …

【Ubuntu】Ubuntu LTS 稳定版更新策略

1、确保下载环境 sudo apt update && sudo apt upgrade -y sudo apt autoremove 2、安装更新管理器 sudo apt install update-manager-core -y 3、设置只更新稳定版 sudo vim /etc/update-manager/release-upgrades 4、开始更新&#xff0c;耐心等待 sudo do-re…

iOS开发进阶(十):viewController生命周期讲解

文章目录 一、生命周期二、注意事项案例讲解 一、生命周期 viewController有自己的生命周期&#xff0c;其生命周期如下图&#xff1a; init - 初始化程序&#xff1b;loadView - 在UIViewController对象的view被访问且为空的时候调用&#xff1b;viewDidLoad - 视图加载完成后…

C语言例4-28:求两个正整数的最大公约数。

算法分析&#xff1a; 输入两个正整数m和nm%n 的余数 r&#xff0c;然后 mn;nr;当 n0, 则m是最大公约数&#xff0c;算法结束&#xff1b;否则转至执行2&#xff0c;重复上述过程&#xff0c;直到n0为止 代码如下&#xff1a; //求两个正整数的最大公约数。 #include<std…