备忘录模式的理解和实践

news2024/12/13 1:36:28

引言

        在软件开发中,我们经常会遇到需要保存对象状态并在某个时间点恢复到该状态的需求。这种需求类似于我们平时说的“后悔药”,即允许用户撤销之前的操作,恢复到某个之前的状态。备忘录模式(Memento Pattern)正是为了解决这类问题而诞生的设计模式之一。本文将详细讲解备忘录模式的概念、原理及其在Java中的实践应用。

一、备忘录模式概述

1.1 定义

        备忘录模式是一种行为设计模式,用于在不暴露对象实现细节的情况下,捕获并保存对象的内部状态,以便以后可以将对象恢复到这个状态。该模式的主要目的是允许用户恢复到对象之前的状态,从而提供某种形式的撤销功能。

1.2 结构

        备忘录模式包含三个主要角色:

  • 发起人(Originator):创建并恢复备忘录的对象。
  • 备忘录(Memento):存储发起人内部状态的快照,并且防止其他对象访问备忘录。备忘录通常只有发起人可以访问其内容。
  • 管理者(Caretaker):负责保存和恢复备忘录,但不能检查或操作备忘录的内容。

1.3 原理

  1. 创建备忘录:发起人通过调用自身的方法创建当前状态的备忘录。
  2. 保存备忘录:管理者接收并保存发起人创建的备忘录。
  3. 恢复状态:发起人通过管理者获取之前保存的备忘录,并恢复到该状态。

二、备忘录模式的优点和缺点

2.1 优点

  • 提供了撤销功能:用户可以通过恢复备忘录来撤销之前的操作。
  • 封装性强:备忘录对象只由发起人创建和解释,外部对象无法直接访问其内容,增强了封装性。
  • 易于实现:备忘录模式相对简单,易于理解和实现。

2.2 缺点

  • 资源开销:保存多个备忘录对象会占用较多的内存资源。
  • 实现复杂:在复杂系统中,创建和恢复备忘录可能需要较多的代码,增加了系统的复杂性。

三、备忘录模式的实践

        下面我们以一个简单的文本编辑器为例,演示如何使用备忘录模式实现撤销功能。

3.1 发起人(Originator)

// 发起人接口
public interface Originator {
    void setState(String state);
    String getState();
    Memento createMemento();
    void setMemento(Memento memento);
}

// 具体的发起人类
public class TextEditor implements Originator {
    private String content;

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

    @Override
    public String getState() {
        return this.content;
    }

    @Override
    public Memento createMemento() {
        return new TextMemento(content);
    }

    @Override
    public void setMemento(Memento memento) {
        if (memento instanceof TextMemento) {
            this.content = ((TextMemento) memento).getContent();
        }
    }
}


3.2 备忘录(Memento)

// 备忘录接口
public interface Memento {
}

// 具体的备忘录类
public class TextMemento implements Memento {
    private String content;

    public TextMemento(String content) {
        this.content = content;
    }

    public String getContent() {
        return content;
    }
}


3.3 管理者(Caretaker)

import java.util.ArrayList;
import java.util.List;

// 管理者类
public class Caretaker {
    private List<Memento> mementoList = new ArrayList<>();

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

    public Memento get(int index) {
        return mementoList.get(index);
    }
}


3.4 客户端代码

public class Client {
    public static void main(String[] args) {
        TextEditor editor = new TextEditor();
        Caretaker caretaker = new Caretaker();

        editor.setState("First state");
        caretaker.add(editor.createMemento());

        editor.setState("Second state");
        caretaker.add(editor.createMemento());

        editor.setState("Third state");

        // 回滚到第二个状态
        System.out.println("Current State: " + editor.getState());
        editor.setMemento(caretaker.get(1));
        System.out.println("Rollback to State: " + editor.getState());

        // 回滚到第一个状态
        editor.setMemento(caretaker.get(0));
        System.out.println("Rollback to State: " + editor.getState());
    }
}


3.5 运行结果

Current State: Third state
Rollback to State: Second state
Rollback to State: First state


四、备忘录模式的应用场景

备忘录模式在实际开发中有很多应用场景,以下是一些常见的例子:

  • 文本编辑器:撤销和重做功能。
  • 数据库事务:保存事务开始前的状态,以便在事务失败时回滚。
  • 游戏开发:保存游戏进度,允许玩家在失败时重新开始。
  • 绘图软件:撤销和重做绘图操作。

总结

        备忘录模式是一种强大的设计模式,用于在不暴露对象内部实现细节的情况下保存和恢复对象的状态。通过引入备忘录对象,我们可以在需要时恢复到对象之前的状态,从而实现撤销功能。虽然备忘录模式在资源开销和实现复杂度上有一些缺点,但在许多应用场景中,它仍然是一种非常有效的解决方案。

        希望本文能帮助你理解备忘录模式,并通过具体的Java代码示例掌握其实现方法。如果你在实际开发中遇到需要撤销功能的需求,不妨尝试一下备忘录模式,相信它会给你的项目带来很大的帮助。

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

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

相关文章

STL——string剖析

STL——string剖析 文章目录 STL——string剖析1. C语言中的字符串2. 标准库中string的使用2.1 构造函数2.2 string的容量操作resize和reserve 2.3 string的增删查改插入操作push_back&#xff1a;insert&#xff1a; 删除操作pop_back&#xff1a;erase 查找操作findfind_firs…

Ubuntu24.04配置STMTrack

项目地址&#xff1a;https://github.com/fzh0917/STMTrack 一、安装 CUDA 参考链接&#xff1a; Ubuntu24.04配置DINO-Tracker Ubuntu多CUDA版本安装及切换 由于之前在其他项目中已经安装了 CUDA12.1&#xff0c;这次需要安装另一个版本。 1. 查看安装版本 按照 requireme…

Android显示系统(08)- OpenGL ES - 图片拉伸

Android显示系统&#xff08;02&#xff09;- OpenGL ES - 概述 Android显示系统&#xff08;03&#xff09;- OpenGL ES - GLSurfaceView的使用 Android显示系统&#xff08;04&#xff09;- OpenGL ES - Shader绘制三角形 Android显示系统&#xff08;05&#xff09;- OpenGL…

【实现多网卡电脑的网络连接共享】

电脑A配备有两张网卡&#xff0c;分别命名为eth0和eth1&#xff08;对于拥有超过两张网卡的情况&#xff0c;解决方案相似&#xff09;。其中&#xff0c;eth0网卡能够连接到Internet&#xff0c;而eth1网卡则通过网线直接与另一台电脑B相连&#xff08;在实际应用中&#xff0…

聊聊在应用层面实现内网穿透功能是否可行

前言 最近接手了供方开发的网关项目&#xff0c;交接文档里面有个内网穿透的功能&#xff0c;一下子就吸引的我的目光。实现这个内网穿透的背景是业务部门有些业务是部署在公网&#xff0c;这些公网的业务想访问内网的业务&#xff0c;但因为公网和内网没打通&#xff0c;导致…

头歌 计算机操作系统 Linux之线程同步二

第1关&#xff1a;信号量 任务描述 在上一个实训中&#xff0c;我们学习了使用互斥锁来实现线程的同步&#xff0c;Linux系统中还提供了另一个类似互斥锁的线程不同操作&#xff0c;那就是信号量。 本关任务&#xff1a;学会使用信号量来实现线程间的同步与互斥。 相关知识 …

基于MinIO打造高可靠分布式“本地”文件系统

MinIO是一款高性能的对象存储服务&#xff0c;而S3协议是由亚马逊Web服务&#xff08;AWS&#xff09;制定的一种标准协议&#xff0c;用于云存储服务之间的数据交换。MinIO与S3协议的关系在于&#xff0c;MinIO实现了S3协议的接口&#xff0c;这意味着用户可以使用与AWS S3相同…

【MIT-OS6.S081作业1.3】Lab1-utilities primes

本文记录MIT-OS6.S081 Lab1 utilities 的primes函数的实现过程 文章目录 1. 作业要求primes (moderate)/(hard) 2. 实现过程2.1 代码实现 1. 作业要求 primes (moderate)/(hard) Write a concurrent version of prime sieve using pipes. This idea is due to Doug McIlroy, in…

Js如和返回数组中的指定列

一、需求 日常工作中需要返回数组中的指定列&#xff0c;例如Echarts 和 下拉框 选择 id&#xff0c;value 类似这种都需要在数组中提取指定列元素。 二、代码示例 const products [{ name: "商品1", price: 100, inventory: 50 },{ name: "商品2", pri…

C++的一些经典算法

以下是C的一些经典算法&#xff1a; 一、排序算法 冒泡排序&#xff08;Bubble Sort&#xff09; 原理&#xff1a; 它重复地走访过要排序的数列&#xff0c;一次比较两个元素&#xff0c;如果它们的顺序错误就把它们交换过来。走访数列的工作是重复地进行直到没有再需要交换…

35.1 thanos项目介绍和二进制部署

本节重点介绍 : 核心优点 无需维护存储&#xff0c;存储高可用&#xff1a; 利用廉价的公有云对象存储&#xff0c;高可用长时间存储&#xff0c;数据降采样&#xff1a;利用Compactor降采样完全适配原生prometheus查询接口&#xff1a;Query实现多级数据缓存配置 二进制部署 …

【PlantUML系列】状态图(六)

一、状态图的组成部分 状态&#xff1a;对象在其生命周期内可能处于的条件或情形&#xff0c;使用 state "State Name" as Statename 表示。初始状态&#xff1a;表示对象生命周期的开始&#xff0c;使用 [*] 表示。最终状态&#xff1a;表示对象生命周期的结束&…

Android 15(V)新功能适配,雕琢移动细节之美

Android 15&#xff0c;内部代号为Vanilla Ice Cream&#xff0c;是Android移动操作系统的最新主要版本&#xff0c;于2024年2月16日在开发者预览版1中发布。Android 15源代码于 2024年9月4日发布。Android 15稳定版于2024年10月15日发布。 以下是针对 Android 15&#xff08;…

【零成本抽象】基本概念与在C++中的实现

零成本抽象概念是由 Bjarne Stroustrup 提出的,他在 1994 年的著作中就有相关设想,2016 年其在 C++ 大会登台演讲时,明确阐述了 C++ 中的 “零成本抽象” 这一理念。 一、零成本抽象概念 Bjarne Stroustrup提出的零成本抽象概念,是指在编程中使用高级抽象机制时,不会产生…

android编译assets集成某文件太大更新导致git仓库变大

不知道大家有没有类似的困扰&#xff0c;你的工程assets文件过大&#xff0c;我曾经在某度车机地图团队工作过一段时间时候&#xff0c;每次发包会集成一个上百MB的文件。工作一段时间你的git仓库将会增加特别多。最后&#xff0c;你会发现你如果重新git clone这个仓库会非常大…

F5-TTS文本语音合成模型的使用和接口封装

F5-TTS文本语音生成模型 1. F5-TTS的简介 2024年10月8日&#xff0c;上海交通大学团队发布&#xff0c;F5-TTS (A Fairytaler that Fakes Fluent and Faithful Speech with Flow Matching) 是一款基于扩散Transformer和ConvNeXt V2的文本转语音 (TTS) 模型。F5-TTS旨在生成流…

克隆选择算法复现

克隆选择算法复现 基于克隆选择算法求解0 - 1背包问题的代码复现文档一、背景和意义&#xff08;一&#xff09;背景&#xff08;二&#xff09;意义 二、算法原理&#xff08;一&#xff09;克隆选择算法基础&#xff08;二&#xff09;受体编辑机制 三、算法流程&#xff08;…

Scala的隐式对象

Scala中&#xff0c;隐式对象&#xff08;implicit object&#xff09;是一种特殊的对象&#xff0c;它可以使得其成员&#xff08;如方法和值&#xff09;在特定的上下文中自动可用&#xff0c;而无需显式地传递它们。隐式对象通常与隐式参数和隐式转换一起使用&#xff0c;以…

观察者模式的理解和实践

引言 在软件开发中&#xff0c;设计模式是开发者们为了解决常见的设计问题而总结出来的一系列最佳实践。观察者模式&#xff08;Observer Pattern&#xff09;是其中一种非常经典且使用率极高的设计模式。它主要用于定义对象之间的一对多关系&#xff0c;使得当一个对象的状态发…

windows下Qt5自动编译配置QtMqtt环境(11)

文章目录 [toc]1、概述2、准备1.1 下载源码1.2 配置环境1.3 解释原理 3、编译4、验证5、参考6、视频 更多精彩内容&#x1f449;内容导航 &#x1f448;&#x1f449;Qt网络编程 &#x1f448; 1、概述 Qt默认是不包含mqtt库的&#xff0c;如果需要使用到mqtt库就只能自己编译配…