设计模式之 备忘录模式

devtools/2024/11/28 3:54:49/

备忘录模式是一种行为型设计模式,它允许你在不暴露对象实现细节的情况下,捕获和保存对象的内部状态。之后,可以通过保存的状态将对象恢复到原先的状态。备忘录模式的核心思想是“在不暴露对象的内部实现的情况下,保存对象的状态,并可以随时恢复这个状态”。

简单来说,备忘录模式帮助我们在某一时刻保存对象的状态,以便以后恢复。

一、备忘录模式的结构

备忘录模式由三个角色组成:

  1. Originator(发起人):负责创建备忘录和使用备忘录来恢复其内部状态。
  2. Memento(备忘录):备忘录对象包含了 Originator 的内部状态,可以在需要时提供给 Caretaker 使用。备忘录不应该对外暴露其内容。
  3. Caretaker(管理者):负责保存备忘录的对象,它不关心备忘录的内容,只知道如何保存和恢复备忘录。Caretaker 通常会持有多个备忘录,以便进行不同的状态恢复。

二、工作原理

备忘录模式的工作原理主要包括以下几个步骤:

  1. 保存状态:当对象的状态发生变化时,发起人对象(Originator)会创建一个备忘录对象(Memento),并将其当前状态存储在备忘录中。
  2. 恢复状态:当需要恢复对象的状态时,发起人会从管理者对象(Caretaker)处获取对应的备忘录,并使用备忘录中的状态信息恢复自身的状态。
  3. 管理备忘录:管理者对象(Caretaker)负责保存多个备忘录,并确保每个备忘录对应的对象状态是可以恢复的。

三、备忘录模式的实现示例

白箱备忘录

白箱备忘录模式是指备忘录对象暴露了内部状态的实现细节,管理者类(Caretaker)不仅能够保存和恢复备忘录,还可以直接访问备忘录中的数据。因此,备忘录是白箱的,它对外部类是透明的,管理者类可以直接读取和修改备忘录的内容。

  • 发起人类
public class Role {private int vit = 100;//生命private int atk = 100;//攻击private int def = 100;//防御public void fight(){this.vit = 0;}public Memento saveMemento(){return new Memento(vit,atk,def);}public void recoverMemento(Memento memento){this.vit = memento.getVit();this.atk = memento.getAtk();this.def = memento.getDef();}public void display(){System.out.println("生命力"+vit);System.out.println("攻击力"+atk);System.out.println("防御力"+def);}}
  • 备忘录类
public class Memento {private int vit;private int atk;private int def;public int getVit() {return vit;}public int getAtk() {return atk;}public int getDef() {return def;}public Memento() {}public Memento(int vit, int atk, int def) {this.vit = vit;this.atk = atk;this.def = def;}
}
  • 管理者类
public class RoleStateCaretaker {private Memento memento;public void setRoleState(Memento memento){this.memento = memento;}public Memento getRoleState(){return memento;}
}
  • 使用备忘录模式
    public class Client {public static void main(String[] args) {System.out.println("----------大战之前的状态--------");Role role = new Role();role.display();RoleStateCaretaker roleStateCaretaker = new RoleStateCaretaker();roleStateCaretaker.setRoleState(role.saveMemento());System.out.println("----------大战之后的状态--------");role.fight();role.display();System.out.println("----------恢复之前状态--------");role.recoverMemento(roleStateCaretaker.getRoleState());role.display();}
    }
  • 运行结果
黑箱备忘录 

黑箱备忘录模式是指备忘录对象完全封装了发起人的状态,外部类(包括管理者类 Caretaker)不能直接访问备忘录中的状态数据。换句话说,备忘录是黑箱的,发起人类是唯一能够读取和修改备忘录内部状态的类。管理者类(Caretaker)只负责保存和恢复备忘录对象,但无法查看备忘录中的数据内容。

针对上述示例,我们定义Memento接口供外部使用,Memento实现类为发起人类的私有内部类

  • 发起人类
    public class Role {private int vit = 100;//生命private int atk = 100;//攻击private int def = 100;//防御public void fight(){this.vit = 0;}public Memento saveMemento(){return new RoleStateMemento(vit,atk,def);}public void recoverMemento(Memento memento){RoleStateMemento roleStateMemento = (RoleStateMemento) memento;this.vit = roleStateMemento.getVit();this.atk = roleStateMemento.getAtk();this.def = roleStateMemento.getDef();}public void display(){System.out.println("生命力"+vit);System.out.println("攻击力"+atk);System.out.println("防御力"+def);}private class RoleStateMemento implements Memento {private int vit;private int atk;private int def;public int getVit() {return vit;}public int getAtk() {return atk;}public int getDef() {return def;}public RoleStateMemento(int vit, int atk, int def) {this.vit = vit;this.atk = atk;this.def = def;}}}
  • 标记接口
    public interface Memento {
    }
    
  • 管理员类
    public class RoleStateCaretaker {private Memento memento;public void setRoleState(Memento memento){this.memento = memento;}public Memento getRoleState(){return memento;}
    }
  • 测试类
    public class Client {public static void main(String[] args) {System.out.println("----------大战之前的状态--------");Role role = new Role();role.display();RoleStateCaretaker roleStateCaretaker = new RoleStateCaretaker();roleStateCaretaker.setRoleState(role.saveMemento());System.out.println("----------大战之后的状态--------");role.fight();role.display();System.out.println("----------恢复之前状态--------");role.recoverMemento(roleStateCaretaker.getRoleState());role.display();}
    }
  • 运行结果

四、备忘录模式的优缺点

优点:
  1. 封装性好备忘录模式可以在不暴露对象内部实现细节的情况下,保存和恢复对象的状态,从而保持了封装性。
  2. 灵活性高:可以随时创建和恢复对象的不同状态,支持“撤销”和“恢复”功能。
  3. 实现简单备忘录模式可以通过简单的对象组合实现,逻辑清晰且易于理解。
缺点:
  1. 内存消耗:如果每次都创建备忘录来保存对象的状态,会导致大量备忘录对象的产生,可能会占用较多内存。
  2. 复杂性增加:当对象的状态非常复杂时,备忘录的管理可能会变得很复杂,尤其是涉及多个状态的保存与恢复时。
  3. 可能会泄露实现细节:尽管备忘录对象的设计要求不能暴露状态信息,但在某些情况下,备忘录对象的实现可能会不小心暴露对象的内部状态。
五、适用场景
  1. 撤销操作:当需要实现操作的撤销功能时,备忘录模式是一个理想的选择。它可以在执行操作前保存状态,以便在撤销时恢复到先前的状态。
  2. 状态恢复:当需要恢复某一时刻的对象状态时,备忘录模式提供了便捷的解决方案。
  3. 版本管理:在版本控制系统中,保存每个版本的状态(如文件的内容或数据库的状态),然后可以随时恢复到某个历史版本。

http://www.ppmy.cn/devtools/137563.html

相关文章

前端自动化运营:提升效率与体验的实践指南

在现代的前端开发与运营中,业务需求的快速变化与用户体验的高标准要求正变得越来越普遍。如何在有限的时间内快速迭代、精准上线、实时响应用户反馈?答案是:前端自动化运营。 本文将从概念出发,结合实际场景,深入探讨前…

OpenOCD之J-Link下载

NOTE:此篇文章由笔者的 VSCode编辑GCC for ARM交叉编译工具链Makefile构建OpenOCD调试(基于STM32的标准库)派生而来。 1.下载USB Dirver Tool.exe,选择J-Link dirver,替换成WinUSB驱动。(⭐USB Dirver Tool…

设计模式-创建型-单例模式

1.概念 该设计模式保证全局只有一个实例对象可以使用,并且自动实例化,向外部提供一个使用接口。 2.作用 保证某些对象在项目中只有一份。 3.应用场景 比如: 全局的计数器——web页面文章阅读计数 全局的资源共享——用户登录后各个页面之…

设计模式学习[9]---模板方法模式

文章目录 前言1.原理阐述1.1 C模板说明1.2 设计模式模板 2.举例3.和原型模式的区别 总结 前言 大型的C项目,都会用到很多模板,C中关于模板的书也不少,那么在设计模式中的模板模式和C的模板又有什么区别呢?模板和上篇的原型又有哪…

Python后端flask框架接收zip压缩包方法

一、用base64编码发送,以及接收 import base64 import io import zipfile from flask import request, jsonifydef unzip_and_find_png(zip_data):# 使用 BytesIO 在内存中处理 zip 数据with zipfile.ZipFile(io.BytesIO(zip_data), r) as zip_ref:extracted_paths…

EasyAnimate:基于Transformer架构的高性能长视频生成方法

这里主要是对EasyAnimate的论文阅读记录,感兴趣的话可以参考一下,如果想要直接阅读原英文论文的话地址在这里,如下所示: 摘要 本文介绍了EasyAnimate,一种利用Transformer架构实现高性能视频生成的高级方法。我们将原…

centos 服务器 docker 使用代理

宿主机使用代理 在宿主机的全局配置文件中添加代理信息 vim /etc/profile export http_proxyhttp://127.0.0.1:7897 export https_proxyhttp://127.0.0.1:7897 export no_proxy"localhost,127.0.0.1,::1,172.171.0.0" docker 命令使用代理 例如我想在使用使用 do…

java基础概念38:正则表达式3-捕获分组

一、定义 分组就是一个小括号。 分组的特点: 二、捕获分组 捕获分组就是把这一组的数据捕获出来,再用一次。 后续还要继续使用本组的数据。 正则内部使用:\\组号正则外部使用:$组号 2-1、正则内部使用:\\组号 示…