java设计模式学习之【备忘录模式】

文章目录

  • 引言
  • 备忘录模式简介
    • 定义与用途
    • 实现方式
  • 使用场景
  • 优势与劣势
  • 在Spring框架中的应用
  • 备忘录示例
  • 代码地址

引言

想象一下,你正在编辑一篇重要的文档,突然你意识到最近的一些更改实际上破坏了文档的结构。幸运的是,你的文本编辑器允许你撤销最近的操作,回到之前的状态。这种能力就像有一个时间机器,可以回到过去,撤销错误的决策。在软件开发中,我们经常需要这种“撤销”功能,备忘录模式为此提供了一种优雅的解决方案。

备忘录模式简介

定义与用途

备忘录模式(Memento Pattern)是一种行为型设计模式,它允许保存一个对象的某个状态,以便在未来某个时刻恢复。这个模式在用户需要撤销或恢复操作时特别有用,它通过引入备忘录对象来捕获和存储对象的内部状态,而不破坏其封装性。

实现方式

实现备忘录模式通常涉及以下几个关键组件:

  • 原发器(Originator):需要保存状态以便后续恢复的对象。
  • 备忘录(Memento):存储原发器对象的内部状态。
  • 看护者(Caretaker):负责保存备忘录,但不修改或检查其内容。

使用场景

备忘录模式适用于以下场景:

  • 当需要保存和恢复对象的历史状态时。
  • 当直接获取对象的状态会暴露其实现细节并破坏对象封装性时。

例如:

  1. 文本编辑器的撤销功能:用户可以撤销最近的编辑操作,并恢复到之前的文本状态。
  2. 游戏保存和加载:在游戏中保存当前进度,玩家可以在以后加载保存点继续游戏。
  3. 软件的快照功能:软件可以定期保存当前状态,以便在出现问题时恢复到工作状态

优势与劣势

  • 优势
    1. 提供了一种恢复状态的灵活方式,而无需暴露对象的内部结构。
    2. 可以简化原发器的职责,因为状态的保存和恢复由备忘录承担。
  • 劣势
    1. 如果用户不断创建备忘录,可能会占用大量内存。
    2. 管理备忘录的成本可能会很高,尤其是如果需要支持多次撤销时。

在Spring框架中的应用

在Spring框架中,虽然备忘录模式不像其他设计模式那样直接显现,但它的核心概念——即保存和恢复对象状态——在某些功能中得到了体现。以下是Spring框架中体现备忘录模式概念的一些方面:

1. Spring Web Flow
在Spring Web Flow中,备忘录模式的概念被用于管理Web应用中的页面流。在用户导航过程中,每个页面的状态都可以被保存,用户可以回退到之前的状态。这类似于备忘录模式中的保存和恢复状态的概念。2. 事务管理
Spring的声明式事务管理允许你在开始一个事务时保存数据库的某种状态,并在事务完成时恢复这种状态。如果事务失败,Spring可以回滚到事务开始之前的状态,这与备忘录模式中保存对象状态以便恢复的概念相符。3. Spring Security的认证和授权
在Spring Security中,用户的认证状态(如安全上下文)在用户会话中保存和恢复。虽然这不是传统意义上的备忘录模式,但它体现了备忘录模式的核心概念——保存和恢复对象的状态。4. 配置和恢复Bean状态
Spring的BeanFactory和ApplicationContext容器允许定义、保存和恢复Bean的配置状态。这些状态信息(如Bean的属性和依赖关系)可以在容器启动时被加载,并在需要时恢复,这与备忘录模式的基本原理类似。

尽管这些应用可能不是备忘录模式的典型示例,但它们都采用了该模式的核心思想——即保存和恢复状态。这些机制在Spring框架中至关重要,有助于实现高效和可靠的状态管理。

备忘录示例

在这里插入图片描述
步骤 1:创建备忘录类

public class Memento {private String state;public Memento(String state){this.state = state;}public String getState(){return state;}    
}

Memento 类包含了对象的状态。它有一个方法 getState() 用于获取保存的状态。

步骤 2:创建原发器类

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 类是要保存状态的对象。它创建备忘录来保存自己的状态,并从备忘录中恢复状态。

步骤 3:创建看护者类

import java.util.ArrayList;
import java.util.List;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 类负责保存备忘录,并在需要时提供备忘录。它维护了一个备忘录列表。

步骤 4:使用看护者和原发器对象

public class MementoPatternDemo {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("当前状态: " + originator.getState());        originator.getStateFromMemento(careTaker.get(0));System.out.println("第一次保存的状态: " + originator.getState());originator.getStateFromMemento(careTaker.get(1));System.out.println("第二次保存的状态: " + originator.getState());}
}

在这里插入图片描述

在这个演示类中,我们创建了一个原发器对象 originator 和一个看护者对象 careTaker。原发器对象更改其状态几次,并保存这些状态到备忘录。通过看护者对象,我们能够恢复原发器对象之前的状态。

这个示例演示了备忘录模式如何用于保存和恢复对象的状态,同时不暴露对象的内部结构。通过这种方式,可以实现如撤销功能这样的操作,而不影响对象的封装性

代码地址

23种设计模式相关代码后续会逐步提交到github上,方便学习,欢迎指点:
代码地址
https://github.com/RuofeiSun/lf-23Pattern

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

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

相关文章

Linux中的gcc\g++使用

文章目录 gcc\g的使用预处理编译汇编链接函数库gcc选项 gcc\g的使用 这里我们需要知道gcc和g实际上是对应的c语言和c编译器&#xff0c;而其他的Java&#xff08;半解释型&#xff09;&#xff0c;PHP&#xff0c;Python等语言实际上是解释型语言&#xff0c;因此我们经常能听…

w4操作系统之windows上创建隐藏用户

隐藏用户–在windows上创建隐藏用户 1.首先查看现有哪些用户。&#xff08;通过net user 命令&#xff09; 2.然后创建隐藏用户&#xff08;net user client$ 123 /add&#xff09; 此时出现报错信息。原因是登录用户没权限。需要用管理员的权限 3.用管理员身份运行cmd&am…

联营商自述被坑惨,加盟库迪没有未来?

撰稿 | 多客 来源 | 贝多财经 近日&#xff0c;库迪联营商在社交平台不约而同发出了致库迪咖啡管理层的公开信&#xff0c;两封公开信可谓字字珠玑&#xff0c;没有一句废话&#xff0c;揭开了库迪咖啡在细节、运营、扩张、培训等方方面面的“背后真相”。 两封公开信 折射库…

无法连接虚拟机设备 ide1:0,因为主机上没有相应的设备。您要每次在开启此虚拟机时都尝试连接此虚拟设备吗?

Vmware报错&#xff1a; 报错原因&#xff1a; ide1:0一般是虚拟机的光驱&#xff0c;配置选项是“使用物理驱动器”&#xff0c;而宿主机可能没有安装光驱&#xff0c;故无法从驱动器上寻找 .ISO 系统文件。 解决方法: 右键点击对应的虚拟机&#xff0c;再点击“设置”按钮。…

windows和Linux如何做强制域名解析

首先我们了解两个问题&#xff1a; 一、域名解析是什么&#xff1f; 域名解析是让我们可以通过网站的域名来找到它对应的IP地址&#xff0c;以便更加方便的访问我们所需访问的网站的一种服务。 它通过DNS服务器来进行&#xff0c;我们输入所想要访问的域名&#xff0c;将会通过…

2024年最新软件测试必问面试题,面试前一天刷效果更佳

1.你为什么选择软件测试行业 因为之前有了解软件测试这个行业&#xff0c;觉得他的发展前景很好。 2.根据你以前的工作经验描述一下软件开发、测试过程&#xff0c;由那些角色负责&#xff0c;你做什么 要有架构师、开发经理、测试经理、程序员、测试员。我在里面主要是负责所…

python3 函数

Python 定义函数使用 def 关键字&#xff0c;一般格式如下&#xff1a; def 函数名&#xff08;参数列表&#xff09;&#xff1a;函数体 让我们使用函数来输出"Hello World&#xff01;"&#xff1a; >>> def hello() :print("Hello World!") &…

处理urllib.request.urlopen报错UnicodeEncodeError:‘ascii‘

参考&#xff1a;[Python3填坑之旅]一urllib模块网页爬虫访问中文网址出错 目录 一、报错内容 二、报错截图 三、解决方法 四、实例代码 五、运行截图 六、其他UnicodeEncodeError: ascii codec 问题 一、报错内容 UnicodeEncodeError: ascii codec cant encode charac…

DBeaver连接hive

1.新建hive连接 其中主机填写hive所在节点地址&#xff0c;端口10000为默认&#xff0c;数据库名不填则是默认default数据库&#xff0c;用户名密码填写hadoop集群中能操作hdfs的用户和密码。 2.编辑驱动&#xff0c;驱动的jar包从安装的hive下的jdbc路径下获取&#xff0c;例…

从 Google Gemini 到 OpenAI Q*(Q-Star):调研重塑生成人工智能(AI)的研究

文章目录 一、前言二、主要内容三、总结 &#x1f349; CSDN 叶庭云&#xff1a;https://yetingyun.blog.csdn.net/ 一、前言 这篇综述探讨了生成式人工智能不断发展的前景&#xff0c;重点关注混合专家&#xff08;MoE&#xff09;、多模态学习的变革性影响&#xff0c;以及对…

C# 的学习难度怎么样?

C# 的学习难度怎么样&#xff1f; 在开始前我有一些资料&#xff0c;是我根据自己从业十年经验&#xff0c;熬夜搞了几个通宵&#xff0c;精心整理了一份「C#的资料从专业入门到高级教程工具包」&#xff0c;点个关注&#xff0c;全部无偿共享给大家&#xff01;&#xff01;&a…

前端实现websocket类封装

随着Web应用程序的发展&#xff0c;越来越多的人开始利用Websocket技术来构建实时应用程序。Websocket是一种在客户端和服务器之间建立持久连接的协议。这种协议可以在一个单独的连接上实现双向通信。与HTTP请求-响应模型不同&#xff0c;Websocket允许服务器自主地向客户端发送…