设计模式之备忘录模式

一、概念

备忘录模式(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、与原型模式结合:

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

八、总结

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

相关推荐
·云扬·3 小时前
Java IO 与 BIO、NIO、AIO 详解
java·开发语言·笔记·学习·nio·1024程序员节
求积分不加C4 小时前
Spring Boot中使用AOP和反射机制设计一个的幂等注解(两种持久化模式),简单易懂教程
java·spring boot·后端
枫叶_v4 小时前
【SpringBoot】26 实体映射工具(MapStruct)
java·spring boot·后端
东方巴黎~Sunsiny4 小时前
java-图算法
java·开发语言·算法
2401_857617625 小时前
汽车资讯新趋势:Spring Boot技术解读
java·spring boot·后端
小林学习编程6 小时前
从零开始理解Spring Security的认证与授权
java·后端·spring
写bug的羊羊6 小时前
Spring Boot整合Nacos启动时 Failed to rename context [nacos] as [xxx]
java·spring boot·后端
努力的小陈^O^6 小时前
docker学习笔记跟常用命令总结
java·笔记·docker·云原生
童先生6 小时前
如何将java项目打包成docker 镜像并且可运行
java·开发语言·docker
feilieren6 小时前
SpringBoot 2.x 整合 Redis
java·开发语言·spring