23种设计模式之备忘录模式

文章目录

概述

备忘录模式(Memento Pattern) 保存一个对象的某个状态,以便在适当的时候恢复对象。备忘录模式属于行为型模式。

在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。

所谓备忘录模式就是在不破坏封装的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样可以在以后将对象恢复到原先保存的状态。使得用户可以方便地回到一个特定的历史步骤,当新的状态无效或者存在问题时,可以使用暂时存储起来的备忘录将状态复原,当前很多软件都提供了撤销操作,其中就使用了备忘录模式。

备忘录模式的优缺点

  • 优点
    1、有时一些发起人对象的内部信息必须保存在发起人对象以外的地方,但是必须要由发起人对象自己读取,这时,
    使用备忘录模式可以把复杂的发起人内部信息对其他的对象屏蔽起来,从而可以恰当地保持封装的边界。
    2、本模式简化了发起人类。发起人不再需要管理和保存其内部状态的一个个版本,客户端可以自行管理他们所需
    要的这些状态的版本。
    3、当发起人角色的状态改变的时候,有可能这个状态无效,这时候就可以使用暂时存储起来的备忘录将状态复原。
  • 缺点
    1、如果发起人角色的状态需要完整地存储到备忘录对象中,那么在资源消耗上面备忘录对象会很昂贵。
    2、当负责人角色将一个备忘录 存储起来的时候,负责人可能并不知道这个状态会占用多大的存储空间,从而无法提醒用户一个操作是否很昂贵。
    3、当发起人角色的状态改变的时候,有可能这个协议无效。如果状态改变的成功率不高的话,不如采取”假如”协议模式。

备忘录模式的结构和实现

模式结构

23种设计模式之备忘录模式
  • Originator(原发器): 它是一个需要保存状态的类,可以创建一个备忘录/备份,并存储它的当前内部状态,也可以使用备忘录来恢复其内部状态。
  • Memento(备忘录): 存储原发器的内部状态。除了原发器类,备忘录类不能被其他类创建和修改。一般通过将Memento类与Originator类定义在同一个包中来实现封装(也可以作为内部类),使用默认访问标识符来定义Memento类,即保证其包内可见。
  • Caretaker(负责人): 负责人又称为管理者,它负责保存备忘录。在负责人类中可以存储一个或多个备忘录对象,它只负责存储对象,而不能修改对象(负责任类只提供备忘录对象的读写接口,不提供备忘录属性的读写接口),也无须知道对象的实现细节。负责人对象可以保存一个备忘录数组,从而实现原发器的多次撤销。

Question:只存储一个备忘录对象是为什么需要负责人对象?

因为包外的客户端无法声明备忘录类的引用,无法获取引用到原发器类创建的备忘录对象,客户端通过引用负责人对象间接引用备忘录对象。

; 模式实现

23种设计模式之备忘录模式

备忘录模式使用三个类 MementoOriginatorCareTaker。Memento 包含了要被恢复的对象的状态。Originator 创建并在 Memento 对象中存储状态。Caretaker 对象负责从 Memento 中恢复对象的状态。

MementoPatternDemo,我们的演示类使用 CareTakerOriginator 对象来显示对象的状态恢复。

Memento.java

public class Memento {
   private String state;

   public Memento(String state){
      this.state = state;
   }

   public String getState(){
      return state;
   }
}

Originator.java

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();
   }
}

CareTaker.java

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);
   }
}

MementoPatternDemo.java

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("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());
   }
}

输出结果:

Current State: State #4
First saved State: State #2
Second saved State: State #3

总结

优点: 1、给用户提供了一种可以恢复状态的机制,可以使用户能够比较方便地回到某个历史的状态。 2、实现了信息的封装,使得用户不需要关心状态的保存细节。

缺点: 消耗资源。如果类的成员变量过多,势必会占用比较大的资源,而且每一次保存都会消耗一定的内存。

使用场景: 1、需要保存/恢复数据的相关状态场景。 2、提供一个可回滚的操作。

注意事项: 1、为了符合迪米特原则,还要增加一个管理备忘录的类。 2、为了节约内存,可使用原型模式+备忘录模式。

这里更多更好哦。。。

🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽

本文作者:Java技术债务
原文链接:https://www.cuizb.top/myblog/article/1661177699
版权声明: 本博客所有文章除特别声明外,均采用 CC BY 3.0 CN协议进行许可。转载请署名作者且注明文章出处。

🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽

23种设计模式之备忘录模式
JVM内存泄漏和内存溢出的原因
JVM常用监控工具解释以及使用
Redis 常见面试题(一)
ClickHouse之MaterializeMySQL引擎(十)
三种实现分布式锁的实现与区别
线程池的理解以及使用
最近面试BAT,整理一份面试资料,覆盖了Java核心技术、JVM、Java并发、SSM、微服务、数据库、数据结构等等。想获取吗?如果你想提升自己,并且想和优秀的人一起进步,感兴趣的朋友,可以在扫码关注下方公众号。资料在公众号里静静的躺着呢。。。
  • 喜欢就收藏
  • 认同就点赞
  • 支持就关注
  • *疑问就评论

一键四连,你的offer也四连

Original: https://www.cnblogs.com/cuizb/p/16709529.html
Author: Java技术债务
Title: 23种设计模式之备忘录模式

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/576220/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • Linux下Oracle单实例配置多监听

    Oracle单实例配置多监听 一、前言 有时候我们项目中需要使用Oracle数据库,同时要需要不同的数据源,而Oracle不像Mysql那样直接建个库即可,Oracle是以账号为单…

    数据库 2023年6月16日
    0124
  • [LeetCode]13. 罗马数字转整数

    罗马数字包含以下七种字符: I, V, X, L,C,D 和 M。 字符 数值 I 1 V 5 X 10 L 50 C 100 D 500 M 1000 例如, 罗马数字 2 写做…

    数据库 2023年6月9日
    0128
  • MySQL完整版详解

    一、数据库的操作 1.创建数据库 如果您在可视化软件上创建数据库,请参阅下图 [En] If you create a database on a visualization so…

    数据库 2023年5月24日
    091
  • macOS快捷键

    1. 最小化所有应用程序 command+option+h+m 2. 同应用窗口切换 command &#xFF5E; 3. 截图 "&#x5168;&a…

    数据库 2023年6月14日
    073
  • 数据库原理四—MySQL日志

    重做日志redo log redo log是重做日志,为InnoDB存储引擎独有。它记录了数据页上的改动。当事务中修改了数据,将会备份存储。当发生数据库服务器宕机或者脏页未写入磁盘…

    数据库 2023年5月24日
    0115
  • MySQL事务提交流程详解

    一. 事务的提交流程。 获取 MDL_key::COMMIT 锁: FTWRL会阻塞 commit 操作。 XID_Event生成并写入binlog cache中。会首先将事务中的…

    数据库 2023年5月24日
    091
  • [javaweb]jsp,jstl,el表达式的使用

    jsp java server page:java服务器前端页面,和servlet一样,用于动态web开发。 特点: 写jsp页面就像在写html html只给用户提供静态数据,j…

    数据库 2023年6月16日
    082
  • md5解密异常

    javax.crypto.BadPaddingException: Given final block not properly paddedat com.sun.crypto.p…

    数据库 2023年6月11日
    094
  • 获取不到数据库连接问题

    org.springframework.jdbc.CannotGetJdbcConnectionException: Could not get JDBC Connection; …

    数据库 2023年6月11日
    080
  • 读取resources下的资源

    这里我通过一个普通的SpringBoot项目进行测试,当然其他项目也都是通用的。 将其中的Test修改为你的类名即可: java;gutter:true; import lombo…

    数据库 2023年6月14日
    078
  • Python–迭代器

    区分:迭代器 Iterator &#x548C;&#x53EF;&#x8FED;&#x4EE3;&#x5BF9;&#x8C61;It…

    数据库 2023年6月9日
    0106
  • MySQL知识点总结(完整版)

    登录和退出MySQL服务器 &#x767B;&#x5F55;MySQL $ mysql -u root -p12345612 &#x9000;&#x…

    数据库 2023年5月24日
    065
  • 简析XDP的重定向机制

    GreatSQL社区原创内容未经授权不得随意使用,转载请联系小编并注明来源。 GreatSQL是MySQL的国产分支版本,使用上与MySQL一致。 一. XDP Socket示例解…

    数据库 2023年6月11日
    085
  • 力扣数据库题目176第二高的薪水

    力扣数据库题目176第二高的薪水 题目 编写一个 SQL 查询,获取 Employee 表中第二高的薪水(Salary) 。 +—-+——&#8…

    数据库 2023年6月9日
    097
  • [Unity]如何解决带刚体的物体在墙角会穿墙的问题

    问题背景 当一个物体在两个带碰撞体的方块组成的墙角时,只要”挤一挤”就可以从墙角穿墙而过: 原因分析 根据【Unity】Rigidbody.velocity…

    数据库 2023年6月16日
    0168
  • MySQL架构

    1_逻辑架构 1.1.连接层 系统(客户端)访问MySQL服务器前,做的第一件事就是 &#x5EFA;&#x7ACB;TCP&#x8FDE;&#x6…

    数据库 2023年5月24日
    0100
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球