【设计模式深度剖析】【8】【行为型】【备忘录模式】| 以后悔药为例加深理解

👈️上一篇:观察者模式
设计模式-专栏👈️

文章目录

备忘录模式

备忘录模式(Memento Pattern)又称为快照(Snapshot)模式或Token模式。

备忘录模式就像我们在生活中使用的"后悔药"。有时候,我们可能会做出一些决定或操作,但事后可能会后悔,希望回到之前的状态。备忘录模式就是这样一种"后悔药",它能够帮助我们在需要的时候,返回到之前的状态。比如,在写文档时,如果我们不小心删除了一个重要的段落,使用备忘录模式,我们就可以轻松地恢复到删除之前的状态。但是,这种"后悔药"也有副作用,那就是它可能会占用一些资源,就像我们需要空间来保存这些后悔的机会一样。

定义

英文原话

Without violating encapsulation,capture and externalizean object's internal state so that the object can be restored to this state later.

直译

在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。以便之后可以将该对象恢复到原先保存的状态。

如何理解呢?

有时有必要记录一个对象的内部状态。

为了允许用户取消不确定的操作或从错误中恢复过来,需要实现检查点和取消机制,而要实现这些机制,你必须事先将状态信息保存在某处,这样才能将对象恢复到他们先前的状态。

但是对象通常封装了其部分或所有的状态信息,使得其状态不能被其他对象访问,也就不可能在该对象之外保存其状态。

而暴露其内部状态又将违反封装的原则,可能有损应用的可靠性和可扩展性。

我们可以用备忘录(Memento)模式解决这一问题。

一个备忘录(memento)是一个对象,他存储另一个对象 (原发器originator)在某个瞬间的内部状态,而后者称为备忘录的原发器originator)。

当需要设置原发器的检查点时,备份机制向原发器请求一个备忘录。

原发器 用描述当前状态 的信息初始化备忘录

只有原发器(originator)可以向备忘录中存取信息,备忘录对其他的对象不可见。

适用于必须保存一个对象在某一时刻的(部分)状态(以便以后有需要可以恢复回此状态)且如果用接口让其他对象直接得到这些状态,将会暴露对象实现细节并破坏对象的封装性。在这样的场景下使用备忘录(Memento)模式。

3个角色

1. Memento(备忘录)

负责存储Originator对象的内部状态,并可以防止Originator以外的其他对象访问备忘录。

备忘录有两个接口:Caretaker只能看到备忘录的窄接口,他只能将备忘录传递给其他对象;而Originator却可看到备忘录的宽接口,允许它访问返回到先前状态所需要的所有数据。

2. Originator(原发器)

originator创建一个备忘录,用以记录当前时刻它的内部状态。

使用备忘录回复内部状态。

只有创建备忘录的原发器会对他的状态状态进行赋值和检索。

3. Caretaker(负责人)

负责保存好备忘录。

不能对备忘录的内容进行操作或检查。

负责保存与提供备忘录对象,但是不能对备忘录的内容进行访问或者操作。

类图

代码示例

java 复制代码
package com.polaris.designpattern.list3.behavioral.pattern08.memento.classicdemo;

// 备忘录接口
interface Memento {
    // 可能包含一些用于获取状态的方法  
    String getState();
}

// 发起人(Originator)  
class Originator {
    private String state;

    // 创建一个备忘录并保存当前状态  
    public Memento createMemento() {
        return new MementoImpl(state);
    }

    // 恢复发起人状态  
    public void restoreMemento(Memento memento) {
        this.state = ((MementoImpl) memento).getState();
    }

    // 设置发起人状态  
    public void setState(String state) {
        this.state = state;
    }

    // 获取发起人状态  
    public String getState() {
        return state;
    }

    // 备忘录实现类,仅供发起人使用  
    private static class MementoImpl implements Memento {
        private String state;

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

        public String getState() {
            return state;
        }
    }
}

// 管理者(Caretaker)  
class Caretaker {
    private Memento memento;

    // 保存备忘录  
    public void setMemento(Memento memento) {
        this.memento = memento;
    }

    // 获取备忘录  
    public Memento getMemento() {
        return memento;
    }
}

// 使用示例  
public class MementoPatternDemo {
    public static void main(String[] args) {
        Originator originator = new Originator();
        Caretaker caretaker = new Caretaker();

        originator.setState("State #1");
        System.out.println("Current State: " + originator.getState());

        // 保存当前状态  
        caretaker.setMemento(originator.createMemento());

        originator.setState("State #2");
        System.out.println("Current State: " + originator.getState());

        // 恢复之前的状态  
        originator.restoreMemento(caretaker.getMemento());
        System.out.println("Restored State: " + originator.getState());
    }
}

/* Output:
Current State: State #1
Current State: State #2
Restored State: State #1
*///~

在这个例子中,Originator类维护了一个内部状态state,并提供了创建备忘录(createMemento)和恢复状态(restoreMemento)的方法。备忘录的实际实现是MementoImpl类,但它被声明为Originator的私有内部类,因此外部类(如Caretaker)不能直接访问它。Caretaker类负责管理备忘录对象。在MemontoPatternDemo类中,我们展示了如何使用这些类来保存和恢复Originator的状态。

备忘录模式的应用

备忘录模式,又称之为快照模式(Snapshot Pattern),是一种软件设计模式,主要用于保存和恢复对象的内部状态。以下是其主要应用:

  1. 撤销和恢复功能:在Word、PhotoShop等软件中,用户可以撤销之前的操作,或恢复到某个历史状态。备忘录模式能够记录用户的每一步操作,从而实现这一功能。
  2. 电子书的阅读进度:用户在阅读电子书时,可以随时保存阅读进度,下次打开时可以从上次的阅读进度继续阅读。
  3. 软件开发中的版本控制:记录每个版本的代码快照,方便进行版本控制和回溯。
  4. 事务管理:在数据库事务处理中,如果一系列操作不能全部完成,就需要回滚操作,将数据恢复到操作之前的状态。备忘录模式可以记录一系列操作的快照,当需要回滚时,可以恢复到备忘录状态。

备忘录模式的优点

  1. 提供恢复机制:为用户提供一种可以恢复状态的机制,允许在必要时将对象恢复到之前的状态。
  2. 实现内部状态的封装:除了创建它的发起人之外,其他对象都不能够访问这些状态信息,这有助于保持封装的边界。
  3. 简化发起人类:发起人不需要管理和保存其内部状态的各个备份,所有状态信息都保存在备忘录中,并由管理者进行管理,这符合单一职责原则。

备忘录模式的缺点

  1. 资源消耗大:如果要保存的内部状态信息过多或者特别频繁,将会占用比较大的内存资源。
  2. 难以预测存储需求:当负责人角色将一个备忘录存储起来的时候,可能无法预测这个状态会占用多大的存储空间,从而无法提醒用户一个操作是否很昂贵。

备忘录模式的使用场景

备忘录模式适用于需要保存/恢复数据的相关业务场景,如:

  1. 撤销操作:在文本编辑器、图形编辑器等工具中,用户可能需要撤销之前的操作。
  2. 游戏存档:在游戏中,玩家可能需要存档以便在之后恢复游戏进度。
  3. 数据库事务管理:在数据库事务处理中,如果一系列操作不能全部完成,就需要回滚操作,将数据恢复到操作之前的状态。

👈️上一篇:观察者模式
设计模式-专栏👈️

相关推荐
武子康19 分钟前
大数据-230 离线数仓 - ODS层的构建 Hive处理 UDF 与 SerDe 处理 与 当前总结
java·大数据·数据仓库·hive·hadoop·sql·hdfs
武子康21 分钟前
大数据-231 离线数仓 - DWS 层、ADS 层的创建 Hive 执行脚本
java·大数据·数据仓库·hive·hadoop·mysql
苏-言28 分钟前
Spring IOC实战指南:从零到一的构建过程
java·数据库·spring
界面开发小八哥35 分钟前
更高效的Java 23开发,IntelliJ IDEA助力全面升级
java·开发语言·ide·intellij-idea·开发工具
草莓base1 小时前
【手写一个spring】spring源码的简单实现--容器启动
java·后端·spring
Allen Bright1 小时前
maven概述
java·maven
编程重生之路1 小时前
Springboot启动异常 错误: 找不到或无法加载主类 xxx.Application异常
java·spring boot·后端
薯条不要番茄酱1 小时前
数据结构-8.Java. 七大排序算法(中篇)
java·开发语言·数据结构·后端·算法·排序算法·intellij-idea
努力进修1 小时前
“探索Java List的无限可能:从基础到高级应用“
java·开发语言·list
politeboy1 小时前
k8s启动springboot容器的时候,显示找不到application.yml文件
java·spring boot·kubernetes