• 【设计模式(18)】行为型模式之备忘录模式


    个人学习笔记分享,当前能力有限,请勿贬低,菜鸟互学,大佬绕道

    如有勘误,欢迎指出和讨论,本文后期也会进行修正和补充


    前言

    常说,”世上没有后悔药“,现实中的确如此,但在计算机应用中,我们大量提供了”后悔“的机会,以防我们需要弥补自己的”过失“

    比如,游戏玩家非常熟悉的“存档”功能(SL大法好),编辑器的撤销/重做功能功能,数据库与操作系统的备份功能等等

    比如前两天,字节的某老哥删掉了公司的全部1GB以下模型,如果不能恢复数据,恐怕我们讨论的就不只是去留问题了。。。


    即,保存一个对象的某个状态,以便在适当的时候恢复对象

    我们将其称为备忘录模式,又称为快照模式


    1.介绍

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

    主要解决:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,以便以后当需要时能将该对象恢复到原先保存的状态。

    何时使用:需要记录一个对象的内部状态,允许用户取消不确定或者错误的操作,并恢复到他原先的状态

    如何解决:通过一个备忘录类专门存储对象状态。

    关键代码:客户不与备忘录类耦合,与备忘录管理类耦合。

    应用实例:游戏存档;编辑器的撤销/重做;windows系统和浏览器的前进/后退;数据库的事务管理;数据库和操作系统的备份;

    优点:

    • 给用户提供了一种可以恢复状态的机制,使用户能够比较方便地回到某个历史的状态。
    • 实现了信息的封装,使得用户不需要关心状态的保存细节。
    • 简化了发起人。发起人不需要管理和保存其内部状态的各个备份,所有状态信息都保存在备忘录中,并由管理者进行管理,这符合单一职责原则。

    缺点:资源消耗大。如果要保存的内部状态信息过多或者特别频繁,将会占用比较大的内存资源。

    使用场景

    • 需要保存/恢复数据的相关状态的场景
    • 需要回滚操作的场景
    • 需要复制某个状态的场景

    2.结构

    备忘录模式主要包括以下角色

    • 发起人(Originator):记录当前时刻的内部状态信息,提供创建备忘录和恢复备忘录数据的功能,实现其他业务功能,它可以访问备忘录里的所有信息。
    • 备忘录(Memento):负责存储发起人的内部状态,在需要的时候提供这些内部状态给发起人。
    • 管理者(Caretaker):对备忘录进行管理,提供保存与获取备忘录的功能,但其不能对备忘录的内容进行访问与修改。

    备忘录模式的 UML 图


    3.实现步骤

    1. 创建 Memento 类。

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

      备忘录为只读,不允许修改

    2. 创建 Originator 类。

      //发起人
      class Originator {
          private String state;
      
          public void setState(String state) {
              this.state = state;
          }
      
          public String getState() {
              return state;
          }
      
          public Memento saveMemento() {
              return new Memento(state);
          }
      
          public void restoreMemento(Memento m) {
              this.setState(m.getState());
          }
      }
      

      提供对当前状态的查询和修改功能,并提供新增备忘录功能

    3. 创建 CareTaker 类。

      //管理者
      class Caretaker {
          private Deque<Memento> mementos = new ArrayDeque<>();
      
          public void setMemento(Memento m) {
              mementos.push(m);
          }
      
          public Memento getMemento() {
              return mementos.pop();
          }
      }
      

    测试类

    public static void main(String[] args) {
        Originator or = new Originator();
        Caretaker cr = new Caretaker();
        or.setState("S0");
        System.out.println("初始状态:" + or.getState());
        cr.setMemento(or.saveMemento()); //保存状态
        or.setState("S1");
        System.out.println("新的状态:" + or.getState());
        or.restoreMemento(cr.getMemento()); //恢复状态
        System.out.println("恢复状态:" + or.getState());
    }
    

    运行结果

    image-20210628162234641


    后记

    实际开发中,备忘录模式出现的并不多,因此也没有什么案例和变型好讲。。。。


    作者:Echo_Ye

    WX:Echo_YeZ

    Email :echo_yezi@qq.com

    个人站点:在搭了在搭了。。。(右键 - 新建文件夹)

  • 相关阅读:
    联想Thinkpad L460安装Win7 64位
    2019牛客暑期多校训练营(第六场)E 构造、原图是补图的同构图
    网络流24题 P2766 最长不下降子序列问题
    The 2019 ICPC China Nanchang National Invitational and International Silk-Road Programming Contest B、H
    P4781 拉格朗日插值
    P4717 快速沃尔什变换FWT 模板题
    2019CCPC-江西省赛C题 HDU6569 GCD预处理+二分
    Gym 101917 E 简单计算几何,I 最大流
    51 Nod 1238 最小公倍数之和 V3 杜教筛
    51Nod 1237 最大公约数之和 V3 杜教筛
  • 原文地址:https://www.cnblogs.com/silent-bug/p/14945118.html
Copyright © 2020-2023  润新知