设计模式之备忘录模式

一、概念

备忘录模式(Memento Pattern)是一种行为型设计模式,它允许在不破坏对象封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样,以后就可以将该对象恢复到原先保存的状态。该模式又叫快照模式。备忘录模式的核心是设计备忘录类以及用于管理备忘录的管理者类。

二、功能

备忘录模式的主要功能包括:

1、捕获和存储状态

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

2、恢复状态

在需要的时候,将对象恢复到之前保存的状态。

三、使用场景

备忘录模式适用于以下场景

1、需要保存与恢复数据的场景

例如,玩游戏时的中间结果的存档功能。

2、需要提供撤销操作的场景

例如,Word、记事本、Photoshop、Eclipse等软件在编辑时按 Ctrl+Z 组合键,还有数据库中事务操作。

3、避免重复计算的场景

例如,计算斐波那契数列时,可以通过备忘录模式保存已经计算过的中间结果,避免重复计算。

需要将一个对象的状态作为参数传递给其他对象的场景:例如,从数据库中查询数据,可以将查询结果的状态保存在备忘录中,然后传递给其他对象。

以下是一个简单的Java代码示例,展示了如何使用备忘录模式实现文本编辑器的撤销功能。

csharp 复制代码
// 备忘录类 - 保存文本编辑器的状态  
class EditorMemento {  
    private String content;  
  
    public EditorMemento(String content) {  
        this.content = content;  
    }  
  
    public String getContent() {  
        return content;  
    }  
}  
  
// 原发器类 - 文本编辑器  
class TextEditor {  
    private String content;  
  
    public void setContent(String content) {  
        this.content = content;  
    }  
  
    public String getContent() {  
        return content;  
    }  
  
    public EditorMemento save() {  
        return new EditorMemento(content);  
    }  
  
    public void restore(EditorMemento memento) {  
        content = memento.getContent();  
    }  
}  
  
// 客户端代码  
public class Main {  
    public static void main(String[] args) {  
        TextEditor editor = new TextEditor();  
        editor.setContent("Hello, World!"); // 设置初始内容  
        System.out.println("初始内容: " + editor.getContent());  
  
        EditorMemento memento = editor.save(); // 保存状态  
        editor.setContent("Hello, OpenAI!"); // 修改内容  
        System.out.println("修改后的内容: " + editor.getContent());  
  
        editor.restore(memento); // 恢复到之前的状态  
        System.out.println("恢复后的内容: " + editor.getContent());  
    }  
}

在这个示例中,我们定义了备忘录类EditorMemento,用于保存文本编辑器TextEditor的状态。TextEditor类提供了设置内容、获取内容、保存状态和恢复状态的方法。客户端代码演示了文本编辑器的使用,包括修改内容、保存状态和恢复状态等操作。

四、备忘录模式的结构

备忘录模式的主要角色包括:

1、发起人(Originator)

记录当前时刻的内部状态信息,提供创建备忘录和恢复备忘录数据的功能,实现其他业务功能,它可以访问备忘录里的所有信息。

2、备忘录(Memento)

负责存储发起人的内部状态,在需要的时候提供这些内部状态给发起人。

3、管理者(Caretaker)

对备忘录进行管理,提供保存与获取备忘录的功能,但其不能对备忘录的内容进行访问与修改。

下面是一个详细的实现,包括发起人、备忘录和管理者三个角色的完整代码。

csharp 复制代码
// 备忘录类  
class Memento {  
    private String state;  
  
    public Memento(String state) {  
        this.state = state;  
    }  
  
    public void setState(String state) {  
        this.state = state;  
    }  
  
    public String getState() {  
        return state;  
    }  
}  
  
// 发起人类  
class Originator {  
    private String state;  
  
    public void setState(String state) {  
        this.state = state;  
    }  
  
    public String getState() {  
        return state;  
    }  
  
    public Memento createMemento() {  
        return new Memento(state);  
    }  
  
    public void restoreMemento(Memento m) {  
        this.setState(m.getState());  
    }  
}  
  
// 管理者类  
class Caretaker {  
    private Memento memento;  
  
    public void setMemento(Memento m) {  
        memento = m;  
    }  
  
    public Memento getMemento() {  
        return memento;  
    }  
}  
  
// 测试代码  
public class MementoPatternDemo {  
    public static void main(String[] args) {  
        Originator originator = new Originator();  
        Caretaker caretaker = new Caretaker();  
  
        originator.setState("State1");  
        System.out.println("初始状态: " + originator.getState());  
  
        caretaker.setMemento(originator.createMemento()); // 保存状态  
        originator.setState("State2");  
        System.out.println("新的状态: " + originator.getState());  
  
        originator.restoreMemento(caretaker.getMemento()); // 恢复状态  
        System.out.println("恢复状态: " + originator.getState());  
    }  
}

在这个示例中,我们定义了备忘录类Memento,用于存储发起人的状态信息。发起人类Originator提供了设置状态、获取状态、创建备忘录和恢复备忘录数据的方法。管理者类Caretaker负责保存和获取备忘录对象。测试代码演示了如何使用备忘录模式来保存和恢复状态。

五、备忘录模式的优点

1、封装性好:

备忘录模式允许在不破坏对象封装性的前提下,捕获和存储对象的内部状态。

2、灵活性高:

通过备忘录模式,可以在需要时轻松地将对象恢复到之前的状态,提供了很大的灵活性。

3、易于扩展:

备忘录模式的设计使得添加新的状态保存和恢复功能变得相对容易。

六、备忘录模式的缺点

1、资源占用:

备忘录模式会额外占用磁盘或内存等资源,尤其是在需要恢复大量状态信息时。

2、实现复杂度:

在某些情况下,实现备忘录模式可能会增加代码的复杂度。

七、与其他模式的关系

1、与命令模式结合:

可以同时使用命令模式和备忘录模式来实现撤销操作。命令模式用于对目标对象执行各种不同的操作,备忘录模式用来保存一条命令执行前该对象的状态。

2、与迭代器模式结合:

可以同时使用备忘录模式和迭代器模式来获取当前迭代器的状态,并在需要的时候进行回滚。

3、与原型模式结合:

在某些情况下,原型模式可以作为备忘录模式的一个简化版本,特别是当需要存储的对象的状态比较简单时。

八、总结

备忘录模式是一种非常有用的行为型设计模式,它允许在不破坏对象封装性的前提下,捕获和存储对象的内部状态,并在需要时进行恢复。该模式广泛应用于需要保存和恢复数据、提供撤销操作、避免重复计算等场景。通过合理的设计和实现,备忘录模式可以大大提高软件的灵活性和可维护性。然而,它也存在一些缺点,如资源占用和实现复杂度等,需要在具体应用中权衡利弊。

相关推荐
Lhappy嘻嘻1 小时前
Java IO|File 文件操作 + 字节流 / 字符流完整笔记 + 递归删除文件实战
java·笔记·php
伊玛目的门徒1 小时前
试用leetcode之典中典 二数之和问题
java·算法·leetcode
懒鸟一枚4 小时前
深入理解 Linux 内存、Swap 交换分区与分页机制的关系
java·linux·数据库
我命由我123456 小时前
执行 Gradle 指令报错,无法将“grep”项识别为 cmdlet、函数、脚本文件或可运行程序的名称
android·java·java-ee·android studio·android jetpack·android-studio·android runtime
考虑考虑6 小时前
Sentinel安装
java·后端·微服务
凤凰院凶涛QAQ7 小时前
《Java版数据结构 & 集合类剖析》栈与队列:“push/pop 是栈的灵魂,offer/poll 是队列的骨架——四组 API,两种人生”
java·开发语言·数据结构
掘金_答案8 小时前
上线那天,一个 ConcurrentHashMap 差点送走我的 AI 客服——3 天排查 JVM 血泪史
java·后端·架构
猿与禅9 小时前
CosId 分布式 ID 生成器完全教程:从架构原理到生产落地
java·shardingsphere·雪花算法·分布式id·高性能·cosid·号段模式
MindUp9 小时前
企业网盘权限模型解析:多层级访问控制与审计能力选型指南
java·linux·运维
NG4779 小时前
【软件设计与体系结构】-策略设计模式
java·设计模式·软件工程