目录
备忘录模式(Memento Pattern)是一种行为型设计模式,它允许在不破坏封装性的前提下捕获和存储一个对象的内部状态,并在以后能够恢复该对象到之前的状态。备忘录模式主要用于撤销操作,或者在需要保存和恢复对象状态的情况下使用。
备忘录模式的关键组成部分
- 备忘录(Memento):存储发起人(Originator)的状态信息,可以是内部状态或外部状态。
- 发起人(Originator):创建备忘录,并使用备忘录恢复其状态。
- 管理者(Caretaker):负责保存和提供备忘录,但不应该操作备忘录的内容。
备忘录模式的应用场景
备忘录模式适用于以下情况:
- 当需要保存和恢复数据的状态时。
- 当一个操作需要在一个对象链中回滚时。
- 当需要实现“撤销”功能时。
备忘录模式的实现步骤
- 定义备忘录类,用于存储状态信息。
- 实现发起人类,创建备忘录并恢复状态。
- 实现管理者类,负责备忘录的保存和恢复。
备忘录模式的示例
假设我们正在编写一个文本编辑器,用户可以在编辑过程中随时保存当前的状态,然后可以恢复到之前保存的任意状态。
步骤1:定义备忘录类
c
深色版本
1#include <stdio.h>
2#include <string.h>
3
4typedef struct Memento {
5 char state[100]; // 存储状态
6} Memento;
7
8// 创建备忘录
9Memento* createMemento(const char *state) {
10 Memento* memento = (Memento*)malloc(sizeof(Memento));
11 strcpy(memento->state, state);
12 return memento;
13}
14
15// 释放备忘录
16void destroyMemento(Memento* memento) {
17 free(memento);
18}
步骤2:实现发起人类
c
深色版本
1typedef struct Editor {
2 char currentState[100]; // 当前状态
3} Editor;
4
5Editor* createEditor() {
6 Editor* editor = (Editor*)malloc(sizeof(Editor));
7 return editor;
8}
9
10void setState(Editor* editor, const char *state) {
11 strcpy(editor->currentState, state);
12}
13
14char* getState(Editor* editor) {
15 return editor->currentState;
16}
17
18Memento* saveState(Editor* editor) {
19 return createMemento(editor->currentState);
20}
21
22void restoreState(Editor* editor, Memento* memento) {
23 strcpy(editor->currentState, memento->state);
24}
25
26void destroyEditor(Editor* editor) {
27 free(editor);
28}
步骤3:实现管理者类
c
深色版本
1typedef struct Caretaker {
2 Memento* mementos[100]; // 备忘录数组
3 int count; // 当前备忘录的数量
4} Caretaker;
5
6Caretaker* createCaretaker() {
7 Caretaker* caretaker = (Caretaker*)malloc(sizeof(Caretaker));
8 caretaker->count = 0;
9 return caretaker;
10}
11
12void addMemento(Caretaker* caretaker, Memento* memento) {
13 caretaker->mementos[caretaker->count++] = memento;
14}
15
16Memento* getMemento(Caretaker* caretaker, int index) {
17 return caretaker->mementos[index];
18}
19
20void destroyCaretaker(Caretaker* caretaker) {
21 for (int i = 0; i < caretaker->count; i++) {
22 destroyMemento(caretaker->mementos[i]);
23 }
24 free(caretaker);
25}
步骤4:客户端代码
c
深色版本
1int main() {
2 Editor* editor = createEditor();
3 Caretaker* caretaker = createCaretaker();
4
5 setState(editor, "Initial state");
6 printf("Current State: %s\n", getState(editor));
7
8 Memento* memento1 = saveState(editor);
9 addMemento(caretaker, memento1);
10
11 setState(editor, "Second state");
12 printf("Current State: %s\n", getState(editor));
13
14 Memento* memento2 = saveState(editor);
15 addMemento(caretaker, memento2);
16
17 setState(editor, "Third state");
18 printf("Current State: %s\n", getState(editor));
19
20 // 恢复到第一个状态
21 restoreState(editor, caretaker->mementos[0]);
22 printf("Restored State: %s\n", getState(editor));
23
24 // 恢复到最后一个状态
25 restoreState(editor, caretaker->mementos[1]);
26 printf("Restored State: %s\n", getState(editor));
27
28 destroyEditor(editor);
29 destroyCaretaker(caretaker);
30
31 return 0;
32}
运行结果
当你运行上述 main
函数时,你会看到以下输出:
深色版本
1Current State: Initial state
2Current State: Second state
3Current State: Third state
4Restored State: Initial state
5Restored State: Second state
备忘录模式的优点
- 封装性:备忘录模式保持了发起人状态的封装性,因为备忘录对外部来说是不透明的。
- 灵活性:备忘录模式使得状态的保存和恢复变得更加灵活。
- 撤销功能:备忘录模式非常适合实现撤销功能。
备忘录模式的缺点
- 内存消耗:备忘录模式可能会消耗大量的内存,尤其是当需要保存大量的状态时。
- 性能开销:频繁地保存和恢复状态可能会带来一定的性能开销。
总结
备忘录模式通过存储和恢复对象的状态,使得对象可以在不同状态之间切换,而无需破坏封装性。这种模式非常适合用于实现撤销功能或需要保存多个状态的历史记录。在使用备忘录模式时,需要注意合理管理内存,避免不必要的内存消耗。