03-JAVA设计模式-备忘录模式

news2024/11/18 16:55:26

备忘录模式

什么是备忘录模式

Java中的备忘录模式(Memento Pattern)是一种行为型设计模式,它允许在不破坏封装性的前提下捕获一个对象的内部状态,并在该对象之外保存这个状态,以便以后可以将对象恢复到原先保存的状态。

主要角色包括:

  • 发起者(Originator):需要保存和恢复状态的对象。它记录当前时刻的内部状态信息,提供创建备忘录和恢复备忘录数据的功能,并可以访问备忘录里的所有信息。
  • 备忘录(Memento):负责存储发起人的内部状态。它是一个临时中间对象,用于存储目标对象的初始相关属性信息。当需要恢复对象的状态时,备忘录提供这些内部状态给发起人。
  • 看护者(Caretaker):对备忘录进行管理,提供保存与获取备忘录的功能。但它不能对备忘录的内容进行访问与修改。

优点:

  • 状态保存与恢复:备忘录模式可以方便地保存和恢复对象的状态,使得对象的状态变化具有可追溯性。
  • 封装性:通过将对象的状态封装在备忘录对象中,备忘录模式可以保持对象的封装性,不会暴露内部状态给外部对象。
  • 简化撤销和重做操作:在需要实现撤销、重做等功能的场景中,备忘录模式可以大大简化操作,提高代码的清晰度和可维护性。

缺点:

  • 资源消耗:如果对象的状态较为复杂或状态变化频繁,备忘录模式可能会消耗较多的内存资源来保存状态。
  • 性能开销:频繁地创建和销毁备忘录对象可能会导致一定的性能开销。
  • 设计复杂性:如果对象的状态需要保密或访问权限受限,备忘录模式可能会增加设计的复杂性,并可能破坏对象的封装性。

常见应用场景:

  • 文本编辑器:在文本编辑器中,备忘录模式可以用于实现撤销和重做功能。当用户编辑文本时,编辑器可以定期保存文本状态到备忘录对象中。当用户需要撤销或重做操作时,编辑器可以恢复或重新应用这些状态。
  • 游戏存档:在电子游戏中,备忘录模式可以用于实现游戏的存档功能。当玩家选择保存游戏时,游戏可以将当前的游戏状态(如玩家位置、分数、物品等)保存到备忘录对象中。当玩家再次加载游戏时,游戏可以从备忘录对象中恢复状态,让玩家继续之前的游戏进度。
  • 数据库事务:在数据库操作中,备忘录模式可以用于实现事务的回滚功能。当执行一系列数据库操作时,可以将数据库的状态保存到备忘录对象中。如果事务执行失败或需要回滚,可以恢复到之前的状态。

案例

java实现控制台输入内容的回退

UML

在这里插入图片描述

实现步骤:

  • 创建发起者ScannerInput,定义保存输入内容字段input
  • 创建备忘录继承发起者,主要继承发起者的属性及get/set方法不再重复提供,提供创建备忘录及通过备忘录恢复状态的方法
  • 创建看护者,定义栈对备忘录进行管理,提供保存与获取备忘录的功能。但它不能对备忘录的内容进行访问与修改

实现代码

ScannerInput.java

// 发起者
public class ScannerInput {
    // 输入内容
    protected String input;
    public ScannerInput(String input) {
        this.input = input;
    }
    public String getInput() {
        return input;
    }
    public void setInput(String input) {
        this.input = input;
    }
}

Originator.java

// 备忘录
//  继承发起者,主要继承发起者的属性及get/set方法不再重复提供
//  提供创建备忘录及通过备忘录恢复状态的方法
public class Originator extends ScannerInput{

    public Originator(String input) {
        super(input);
    }

    // 创建备忘录
    public ScannerInput createMemento() {
        return new ScannerInput(this.input);
    }

    // 恢复
    public void restoreMemento(ScannerInput scannerInput) {
        this.input = scannerInput.getInput();
    }
}

Caretaker.java

import java.util.Stack;

// 看护者
// * 对备忘录进行管理,提供保存与获取备忘录的功能。但它不能对备忘录的内容进行访问与修改。
public class Caretaker {
    // 定义栈管理备忘录
    private Stack<ScannerInput> stack = new Stack<ScannerInput>();

    // 压栈
    public void setScannerInput(ScannerInput scannerInput) {
        stack.push(scannerInput);
    }

    // 出栈
    public ScannerInput getScannerInput() {
        if(stack.size() == 0){
            System.out.println("已经不可以回退啦!");
        }
        return stack.pop();
    }
}

TestClient.java

import java.util.Scanner;

public class TestClient {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入一些文本,输入'exit'退出:");

        // 创建原发器对象并设置默认内容
        Originator originator = new Originator("");
        // 创建并保存备忘录
        Caretaker caretaker = new Caretaker();
        // 初始化压栈
        caretaker.setScannerInput(originator.createMemento());

        while (true) {
            String input = scanner.nextLine();
            if ("exit".equalsIgnoreCase(input)) {
                System.out.printf("你输入了:%s%n" , input);
                break;
            }
            // 回退操作
            else if ("back".equalsIgnoreCase(input)) {
                // 回退
                originator.restoreMemento(caretaker.getScannerInput());
                System.out.printf("回退上一步-你输入:%s%n 输入:back(回退上一步) exit(退出)%n" , originator.getInput());
            } else {
                // 设置内容
                originator.setInput(input);
                // 设置备忘录
                caretaker.setScannerInput(originator.createMemento());
                System.out.printf("你输入了:%s%n 输入:back(回退上一步) exit(退出)%n" , originator.getInput());
            }
        }

        scanner.close();
        System.out.println("已退出。");
    }
}

执行结果:

在这里插入图片描述

gitee源码

git clone https://gitee.com/dchh/JavaStudyWorkSpaces.git

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

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

相关文章

迪拜之行回顾:CESS 的 DePIN 创新之旅

迪拜最近是一个关键热词&#xff0c;成为了一系列 Web3 和加密活动的中心&#xff0c;吸引了行业领导者、创新者和爱好者&#xff0c;探索区块链和去中心化技术的最新发展。从 4 月中旬&#xff0c;一系列行业会议和活动陆续举行&#xff0c;吸引了一众与会者。然而暴雨积水又成…

iframe实现pdf预览,并使用pdf.js修改内嵌标题,解决乱码问题

项目中遇到文件预览功能,并且需要可以打印文件.下插件对于内网来说有点麻烦,正好iframe预览比较简单,且自带下载打印等功能按钮. 问题在于左上方的文件名乱码,网上找了一圈没有看到解决的,要么就是要收费要会员(ztmgs),要么直接说这东西改不了. 使用: 1.引入 PDF.js 库&…

OpenCV实现霍夫变换

返回:OpenCV系列文章目录&#xff08;持续更新中......&#xff09; 上一篇&#xff1a;OpenCV 如何实现边缘检测器 下一篇 :OpenCV 实现霍夫圆变换 目标 在本教程中&#xff0c;您将学习如何&#xff1a; 使用 OpenCV 函数 HoughLines()和 HoughLinesP()检测图像中的线条。…

云赛道---人工智能概述(重点总结)决赛准备

1、人工智能的一个比较流行的定义&#xff0c;也是该领域较早的定义&#xff0c;是由约翰 麦卡锡&#xff08; John McCarthy| &#xff09;在 1956 年的达特矛斯会议&#xff08; Dartmouth Conference &#xff09;上提出的&#xff1a;人工 智能就是要让机器的行为看起来…

书生·浦语 大模型(学习笔记-5)XTuner 微调 LLM:1.8B、多模态、Agent

目录 一&#xff1a;两种微调 二、数据的一生 三、微调方案 四、XTuner 五、InternLM2 1.8B模型&#xff08;相关知识&#xff09; 一&#xff1a;两种微调 增量与训练和指令微调的区别 二、数据的一生 原始数据转换为标准格式数据 添加对话模板&#xff0c;直接调用即可…

【Ajax-异步刷新技术】什么是Ajax之续章 !

文章目录 Ajax第五章1、layui的后台布局2、layui的数据表格1、在jsp页面中编写table2、在页面中引入文件3、编写代码4、参照文档修改表格属性 **3、最终效果** 第六章1、继续第五章内容1、layui组件2、添加数据3、查看数据4、修改数据5、删除数据 2、批量删除核心 3、数据表格重…

C++ 核心编程 - 内存分区模型

文章目录 1.1 程序运行前1.2 程序运行后1.3 new 操作符 C 程序在执行时&#xff0c;将内存大致划分为 4个区域&#xff1a; 代码区&#xff1a;存放函数体的二进制代码&#xff0c;由操作系统进行管理&#xff1b;全局区&#xff1a;存放全局变量和静态变量以及常量&#xff1…

新媒体运营-----短视频运营-----PR视频剪辑----软件基础

新媒体运营-----短视频运营-----PR视频剪辑-----持续更新(进不去说明我没写完)&#xff1a;https://blog.csdn.net/grd_java/article/details/138079659 文章目录 1.1 PR软件重置与初始化设置1.2 新建项目及序列设置1.3 PR工作区的管理方法1.4 导入4K超高清视频并与ME配合工作1…

Unity 按下Play键后,Scene View里面一切正常,但是Game View中什么都没有 -- Camera Clear Flags的设置

问题如下所示。 最先遇到这个问题是我想用Unity开发一个VR 360-degree Image Viewer。在Scene View中可以看到球体&#xff0c;但是Game View什么都看不到。最后找到的原因是&#xff0c;我使用的shader是Skybox/Panorama&#xff0c; 需要把Main Camera的Clear Flags设置成Do…

FPGA实现AXI4总线的读写_如何写axi4逻辑

FPGA实现AXI4总线的读写_如何写axi4逻辑 一、AXI4 接口描述 通道信号源信号描述全局信号aclk主机全局时钟aresetn主机全局复位&#xff0c;低有效写通道地址与控制信号通道M_AXI_WR_awid[3:0]主机写地址ID&#xff0c;用来标志一组写信号M_AXI_WR_awaddr[31:0]主机写地址&…

mongodb使用debezium

前置 服务器上需要安装jdk11 jdk下载地址 kafka安装 官网下载地址 安装教程 debezium 安装 运行 Debezium 连接器需要 Java 11 或更高版本 Debezium 并不是一个独立的软件&#xff0c;而是很多个 Kafka 连接器的总称。这些 Kafka 连接器分别对应不同的数据库&#xff0c;…

6、ES单机设置用户名密码、集群设置用户名密码、es-head登录、如何去掉密码

目录 一、ES单节点密码配置1、修改配置文件2、 重启es服务3&#xff0c;执行修改密码命令4、访问服务 二、ES集群密码配置1、确定主节点2、生成elastic-stack-ca.p123、生成elastic-certificates.p124、修改配置文件并重启集群5、进行密码配置6、验证 三、es-head登录增加密码的…

串口调速小车1

1. 让小车动起来 智能小车1-智能小车的初认识_void motor-CSDN博客 接线 B-1A -- PB0 B-1B -- PB1 A-1A -- PB2 A-1B -- PB10 CubeMx 1.常规配置 SYS->Debug->Serial Wire RCC->High Speed Clock(HSE)->Crystal/Ceramic Resonator 时钟树HSE、PLLCLK打开…

【Webgl_glslThreejs】搬运分享shader_飘落心形

来源网站 https://www.shadertoy.com/view/4sccWr效果预览 代码演示 将shadertory上的代码转成了threejs可以直接用的代码&#xff0c;引入文件的material&#xff0c;并在创建mesh或已有物体上使用material即可&#xff0c;使用时请注意uv对齐。 import { DoubleSide, Shad…

ROM修改进阶教程------如何去除安卓机型系统的开机向导 几种操作步骤解析

在和很多工作室定制化系统中。手机在第一次启动的时候系统都会进入设置向导,虽然可以设置手机的基本配置。但有很多客户需要去除手机的开机向导来缩短开机时间。确保手机直接进入工作状态。那么今天的教程针去除对开机向导的几种方法做个解析。机型很多版本不同。操作也有不同…

【产品经理修炼之道】- 从需求到功能的转化过程

产品经理的最大作用是将需求转化为产品或者功能&#xff0c;从需求到功能&#xff0c;会经历哪些过程&#xff1f;本文总结了从需求到功能的转化过程&#xff0c;希望对你进一步了解有所帮助。 “大部分的产品经理特别是数字化产品经理其核心价值就是如何去解决如何把需求转化为…

JAVAEE—HTTPS和ssl证书

0[toc] 什么是HTTPS HTTPS 也是一个应用层协议. 是在 HTTP 协议的基础上引入了一个加密层. HTTP 协议内容都是按照文本的方式明文传输的. 这就导致在传输过程中出现一些被篡改的情况而HTTPS则是新采用加密的方式进行传输 为什么需要HTTPS 为什么要使用HTTPS呢&#xff1f;这…

关于浏览器360导航无法更改

当前环境场景&#xff1a; 浏览器&#xff1a;Microsoft Edge 版本 121.0.2277.106 (正式版本) (64 位) 系统&#xff1a;Windows 11 家庭中文版 23H2 问题描述 首先出现这种情况会让我们非常的气愤但是又束手无策&#xff0c;看到这个页面简直就恨的牙根痒痒&#xff0c;但是…

VMware配置centos虚拟机实现内网互通

VMware配置centos虚拟机实现内网互通 一、安装无桌面模式 环境说明&#xff1a; VMWare版本&#xff1a;VMware Workstation 17 Pro Centos版本&#xff1a;CentOS-7.9-x86_64-DVD-2009.iso 一键下载本文资源包 1. 安装虚拟机 下面是创建具体步骤,其中需要注意的是&#xff1…

OpenHarmony开源软件供应链安全风险

慕冬亮&#xff0c;华中科技大学网络空间安全学院副教授&#xff0c;武汉英才&#xff0c;华中科技大学OpenHarmony技术俱乐部、开放原子开源社团指导教师。研究方向为软件与系统安全&#xff0c;在国际安全会议上发表十余篇论文&#xff0c;并获得ACM CCS 2018杰出论文奖。创立…