大数据知识体系
首页
数据结构与算法
  • JVM
  • Java
  • Scala
  • Python
设计模式
  • MySQL
  • Redis
  • HDFS
  • HBase
  • ClickHouse
  • ElasticSearch
  • Iceberg
  • Hudi
  • Spark
  • Flink
  • Hive
  • Yarn
  • Zookeeper
  • Maven
  • Git
  • 数据仓库
  • 用户画像
  • 指标体系
数据治理
关于
首页
数据结构与算法
  • JVM
  • Java
  • Scala
  • Python
设计模式
  • MySQL
  • Redis
  • HDFS
  • HBase
  • ClickHouse
  • ElasticSearch
  • Iceberg
  • Hudi
  • Spark
  • Flink
  • Hive
  • Yarn
  • Zookeeper
  • Maven
  • Git
  • 数据仓库
  • 用户画像
  • 指标体系
数据治理
关于
  • 设计模式概述
  • 创建型模式

    • 单例模式
    • 简单工厂模式
    • 工厂方法模式
    • 抽象工厂模式
    • 建造者模式
    • 原型模式
  • 结构型模式

    • 适配器模式
    • 装饰器模式
    • 代理模式
    • 外观模式
    • 桥接模式
    • 组合模式
    • 享元模式
  • 行为型模式

    • 策略模式
    • 模板方法模式
    • 观察者模式
    • 迭代器模式
    • 责任链模式
    • 命令模式
    • 备忘录模式
      • 一、概述
        • 1.1 解决了什么问题
        • 1.2 解决方案
      • 二、实现方式
        • 2.1 角色
        • 2.2 代码
      • 三、源码中的应用
    • 状态模式
    • 访问者模式
    • 中介者模式
    • 解释器模式
  • 设计模式
  • 行为型模式
Will
2022-03-29
目录

备忘录模式

# 一、概述

备忘录(Memento)模式在不破坏对象的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。

# 1.1 解决了什么问题

不知道你有没有用过 Idea 的 Local History 功能,其实很多编辑器都提供快照恢复功能,当你在某一时刻对文件进行修改之后,它会在本地将当前时刻文件的状态(快照)记录下来。后续如果编辑出错或者因为其它原因,当你需要的时候就可以恢复到过去任意时刻的状态(快照)。备忘录模式就是解决这个问题的,它可以在对象之外保存该对象的状态。

# 1.2 解决方案

备忘录模式将对象状态的副本存储在一个名为备忘录(Memento)的特殊对象中,除了创建备忘录的对象外,任何对象都不能访问备忘录的内容。

# 二、实现方式

# 2.1 角色

  1. Originator:原发器,需要存储的就是这个角色的状态。它可以生成自身状态的快照,也可以在需要时通过快照恢复自身的状态。
  2. Memento:备忘录,原发器的快照对象,也就是说原发器的状态数据会存储在这个类中,通常会通过构造函数一次性传递数据。而且这个类一般是一个 POJO 类,需要保存原发器中的哪些属性的状态,这个类中就有哪些属性。
  3. Caretaker:负责人,负责生成以及记录多个快照。

# 2.2 代码

定义原发器对象:

public class Editor {
    // 文本中的内容
    private String text;

    // 文本长度
    private long length;

    // 最后修改时间
    private long timestamp;

    public void edit(String text) {
        this.text = text;
        this.length = text.length();
        this.timestamp = System.currentTimeMillis();
    }

    @Override
    public String toString() {
        return "Editor{" +
                "text='" + text + '\'' +
                ", length=" + length +
                ", timestamp=" + timestamp +
                '}';
    }

    /**
     * 创建快照
     *
     * @return
     */
    public EditorSnapshot createSnapshot() {
        return new EditorSnapshot(text, length, timestamp);
    }

    /**
     * 恢复快照
     *
     * @param snapshot
     */
    public void restoreSnapshot(EditorSnapshot snapshot) {
        this.text = snapshot.getText();
        this.length = snapshot.getLength();
        this.timestamp = snapshot.getTimestamp();
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45

定义备忘录对象,因为需要保存的是Editor的text、length和timestamp三个属性,所以备忘录对象中也只有这三个字段。

public class EditorSnapshot {

    private String text;

    private long length;

    private long timestamp;

    public EditorSnapshot(String text, long length, long timestamp) {
        this.text = text;
        this.length = length;
        this.timestamp = timestamp;
    }

    public String getText() {
        return text;
    }

    public void setText(String text) {
        this.text = text;
    }

    public long getLength() {
        return length;
    }

    public void setLength(long length) {
        this.length = length;
    }

    public long getTimestamp() {
        return timestamp;
    }

    public void setTimestamp(long timestamp) {
        this.timestamp = timestamp;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

定义负责人,该对象用来管理多个快照,除了下面的增加快照和获取快照,还可以增加删除快照等。

public class Caretaker {
    private List<EditorSnapshot> snapshots = new ArrayList<>();

    /**
     * 保存快照
     *
     * @param snapshot
     */
    public void saveSnapshot(EditorSnapshot snapshot) {
        this.snapshots.add(snapshot);
    }

    /**
     * 获取快照
     *
     * @param index
     * @return
     */
    public EditorSnapshot getSnapshot(int index) {
        return snapshots.get(index);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

示例:

public class MementoTest {
    public static void main(String[] args) {
        Caretaker caretaker = new Caretaker();
        Editor editor = new Editor();

        editor.edit("这是第一份快照");
        caretaker.saveSnapshot(editor.createSnapshot());

        editor.edit("这是第二份快照,多四个字");
        caretaker.saveSnapshot(editor.createSnapshot());

        editor.edit("This is the third snapshot");
        caretaker.saveSnapshot(editor.createSnapshot());

        System.out.println(editor);

        // 恢复第一次的状态
        editor.restoreSnapshot(caretaker.getSnapshot(0));
        System.out.println(editor);

        // 恢复第二次状态
        editor.restoreSnapshot(caretaker.getSnapshot(1));
        System.out.println(editor);

        // 恢复第三次状态
        editor.restoreSnapshot(caretaker.getSnapshot(2));
        System.out.println(editor);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
Editor{text='This is the third snapshot', length=26, timestamp=1663163957886}
Editor{text='这是第一份快照', length=7, timestamp=1663163957885}
Editor{text='这是第二份快照,多四个字', length=12, timestamp=1663163957886}
Editor{text='This is the third snapshot', length=26, timestamp=1663163957886}
1
2
3
4

# 三、源码中的应用

  1. java.io.Serializable
  2. javax.faces.component.StateHolder
上次更新: 2023/11/01, 03:11:44

← 命令模式 状态模式→

Theme by Vdoing | Copyright © 2022-2023 Will 蜀ICP备2022002285号-1
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式