备忘录模式(Memento Pattern)
备忘录模式(Memento Pattern)是一种行为型设计模式,用于在不暴露对象内部实现细节的情况下,捕获对象的内部状态,并在需要时恢复到先前的状态。该模式通常用于需要撤销和恢复操作的场景。
核心思想:在不破坏对象封装的前提下,捕获并保存对象的内部状态,以便在需要时恢复到之前的状态。
主要组成部分
- Originator(发起人):负责创建和保存备忘录对象。它可以恢复到之前的状态。
- Memento(备忘录):存储发起人对象的内部状态,允许发起人恢复到此状态。它通常是一个简单的封装类,只保存状态信息。
- Caretaker(看护者):负责管理备忘录对象的生命周期,保存备忘录,但不会修改备忘录的内容。看护者可以随时请求发起人对象创建备忘录,并在需要时提供备忘录。
案例实现
Git 是一个典型的版本控制工具,适用备忘录模式来实现简化的版本控制。备忘录模式通过保存每个文件或项目的状态快照,允许我们随时恢复到先前的版本。虽然 Git 的实现更加复杂,并且具有更多的功能(如分支管理、合并等),我们可以通过备忘录模式来实现一个简单的版本控制系统。
下面是一个使用备忘录模式模拟简单版本控制的实现:
案例类图

Commit(提交)
提交类包含着所提交的所有信息,这里仅仅记录提交时的备注信息。
java
public class Commit {
private final String content;
public Commit(String content) {
this.content = content;
}
public String getContent() {
return content;
}
}
GitRepository(版本库)
java
public class GitRepository {
private String content;
public GitRepository(String content) {
this.content = content;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
// 创建提交(备忘录)
public Commit saveToCommit() {
return new Commit(content);
}
// 从提交恢复
public void restoreFromCommit(Commit commit) {
this.content = commit.getContent();
}
}
VersionControl(版本控制)
为了简化代码,List的序列号为版本号
java
public class VersionControl {
private List<Commit> commitHistory = new ArrayList<>();
private GitRepository repository;
public VersionControl(GitRepository repository) {
this.repository = repository;
}
// 提交当前状态
public void commit() {
commitHistory.add(repository.saveToCommit());
System.out.println("Committed: " + repository.getContent());
}
// 查看历史提交
public void showHistory() {
System.out.println("Commit History:");
for (int i = 0; i < commitHistory.size(); i++) {
System.out.println("\tCommit " + (i + 1) + ": " + commitHistory.get(i).getContent());
}
}
// 恢复到某个历史提交
public void restore(int commitIndex) {
if (commitIndex >= 0 && commitIndex < commitHistory.size()) {
repository.restoreFromCommit(commitHistory.get(commitIndex));
System.out.println("Restored to: " + repository.getContent());
} else {
System.out.println("Invalid commit index!");
}
}
}
测试代码
java
public class GitDemo {
public static void main(String[] args) {
// 创建一个GitRepository对象,模拟一个文件的内容
GitRepository repository = new GitRepository("初始化仓库");
// 创建版本控制系统
VersionControl versionControl = new VersionControl(repository);
// 提交当前状态
versionControl.commit();
// 修改文件内容并提交
repository.setContent("新增功能");
versionControl.commit();
// 修改文件内容并提交
repository.setContent("修复bugs");
versionControl.commit();
// 查看历史提交
versionControl.showHistory();
// 恢复到第二个提交
versionControl.restore(1);
// 修改并再次提交
repository.setContent("功能调整");
versionControl.commit();
// 查看历史提交
versionControl.showHistory();
}
}
执行结果
Committed: 初始化仓库
Committed: 新增功能
Committed: 修复bugs
Commit History:
Commit 1: 初始化仓库
Commit 2: 新增功能
Commit 3: 修复bugs
Restored to: 新增功能
Committed: 功能调整
Commit History:
Commit 1: 初始化仓库
Commit 2: 新增功能
Commit 3: 修复bugs
Commit 4: 功能调整
代码简析
GitRepository 类模拟一个代码文件的内容,并具有修改内容和创建备忘录(提交)的方法
Commit 类作为备忘录,保存文件的某个版本(即内容)
VersionControl 类充当版本控制系统,负责管理所有提交(备忘录),可以查看提交历史、创建新提交以及恢复历史版本
命令模式和备忘录模式对比
备忘录模式 重点在于保存和恢复状态,用于保存对象的历史状态并在需要时恢复,不改变对象的外部接口。
命令模式 重点在于请求的封装和解耦,用于将请求的发送者和接收者解耦,使得请求者不必知道如何执行操作,增加了操作的灵活性。
举例
备忘录模式 :
假设你有一个文本编辑器,用户输入了一段文本。你可以使用备忘录模式保存文本的状态,当用户点击撤销按钮时,编辑器恢复到之前保存的文本状态。
命令模式 :
假设你在一个远程控制器中,按下按钮后它发送一个命令来打开电视。电视接收命令并执行打开操作。通过命令模式,可以将按钮点击与电视操作解耦,且可以轻松实现撤销和重做功能,或将操作排队执行。
总结
备忘录模式的核心关注点是保存对象的内部状态 ,并在需要时恢复到先前的状态,而不暴露对象的实现细节。这通常用于实现撤销、回退功能。
-
状态管理:备忘录模式允许对象在某一时刻保存状态,并且可以在以后恢复到这个状态。这对于需要撤销或恢复的应用场景非常有用,比如文本编辑器、游戏进度保存等。
-
内部封装:备忘录对象封装了原对象的状态,但不允许外部直接修改这些状态,保护了原对象的内部数据。通常,备忘录对象是"只读"的,只有原对象可以恢复或修改其内容。

需要查看往期设计模式文章的,可以在个人主页中或者文章开头的集合中查看,可关注我,持续更新中。。。