【设计模式(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

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

原文地址:https://www.cnblogs.com/silent-bug/p/14945118.html