备忘录模式(Memento Pattern)是行为型设计模式的重要分支,其核心设计目标是在不破坏对象封装性的前提下 ,捕获对象的内部状态并将其持久化到外部容器,以便在需要时快速将对象恢复至指定历史状态。该模式完美解决了“状态保存与恢复”的核心痛点,广泛应用于撤销操作、数据回滚、快照备份等场景。本文将从核心结构拆解、多语言落地实现、优缺点深度剖析、适用场景梳理及实战总结等维度,系统解读备忘录模式的设计思想与工程实践,为开发者提供可直接复用的技术方案。
一、备忘录模式核心结构 备忘录模式的核心价值在于“封装状态、解耦管理”,通过三大核心角色的协同工作,实现状态的安全保存与灵活恢复,各角色职责边界清晰,无冗余依赖,具体定义与交互逻辑如下:
1.1 原发器(Originator) 原发器是需要进行状态管理的核心业务对象,负责两个核心操作:一是创建备忘录 ,即捕获自身当前的内部状态,并将状态写入备忘录对象;二是恢复状态 ,即从备忘录中读取历史状态,将自身恢复至该状态。原发器是唯一有权限访问备忘录内部状态的角色,确保状态的封装性。
1.2 备忘录(Memento) 备忘录是状态的“容器”,专门用于存储原发器的内部状态,其设计核心是“封装隔离”。为保证状态安全,备忘录仅暴露供原发器读写状态的接口(或仅允许原发器访问其私有状态),其他角色(如管理者)仅能持有备忘录对象,无法修改或直接访问其内部状态,避免破坏原发器的封装性。
1.3 管理者(Caretaker) 管理者是备忘录的“管家”,负责备忘录对象的生命周期管理,包括存储、获取、清理等操作,但不参与状态的读写 。管理者的核心作用是解耦原发器与备忘录的直接依赖,通过统一的接口管理多个备忘录,支持多状态快照的存储与切换(如多步撤销)。
核心交互流程:原发器捕获当前状态 → 创建备忘录并写入状态 → 管理者存储备忘录 → 需恢复状态时,管理者取出指定备忘录 → 原发器从备忘录读取状态并完成恢复。
二、多语言实现备忘录模式 以“文本编辑器撤销功能”为统一实战场景,设计核心逻辑:原发器(编辑器)负责存储当前文本内容,备忘录存储文本快照,管理者管理快照列表,支持多步保存与撤销。以下提供C#、Python、Golang、C++及纯C的可运行实现,贴合各语言原生特性,补充规范注释、边界校验与资源释放逻辑,兼顾实用性与严谨性,清晰呈现模式的适配思路。
2.1 C# 实现(面向对象规范实现) C#作为强类型面向对象语言,通过类封装备忘录状态,依托访问修饰符(private)保证备忘录的封装性,借助泛型与集合优化管理者的备忘录管理逻辑,代码结构清晰、可维护性高,适用于企业级应用的撤销/回滚场景(如办公软件、业务系统配置管理)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 using System;using System.Collections.Generic;public class Memento { public string TextState { get ; private set ; } internal Memento (string textState ) { TextState = textState ?? string .Empty; } } public class Originator { private string _currentText = string .Empty; public void SetText (string text ) { _currentText = text ?? string .Empty; Console.WriteLine($"编辑器更新状态:{_currentText} " ); } public string GetText () => _currentText; public Memento CreateMemento () { return new Memento(_currentText); } public void RestoreMemento (Memento memento ) { if (memento == null ) { Console.WriteLine("警告:备忘录不可为null,无法恢复状态" ); return ; } _currentText = memento.TextState; Console.WriteLine($"编辑器恢复状态:{_currentText} " ); } } public class Caretaker { private readonly Queue<Memento> _mementos = new Queue<Memento>(); private readonly int _maxCount = 10 ; public void AddMemento (Memento memento ) { if (memento == null ) { Console.WriteLine("警告:无法添加空备忘录" ); return ; } if (_mementos.Count >= _maxCount) { _mementos.Dequeue(); Console.WriteLine("提示:快照数量已达上限,移除最旧快照" ); } _mementos.Enqueue(memento); Console.WriteLine($"快照添加成功,当前快照数量:{_mementos.Count} " ); } public Memento GetLatestMemento () { if (_mementos.Count == 0 ) { Console.WriteLine("警告:无历史快照可获取" ); return null ; } var mementoArray = _mementos.ToArray(); return mementoArray[^1 ]; } public Memento GetMemento (int index ) { if (index < 0 || index >= _mementos.Count) { Console.WriteLine("警告:快照索引无效" ); return null ; } return _mementos.ToArray()[index]; } } class Program { static void Main () { try { Originator editor = new Originator(); Caretaker caretaker = new Caretaker(); editor.SetText("第1步:编写备忘录模式核心概念" ); caretaker.AddMemento(editor.CreateMemento()); editor.SetText("第2步:梳理多语言实现思路" ); caretaker.AddMemento(editor.CreateMemento()); editor.SetText("第3步:分析优缺点与使用场景" ); caretaker.AddMemento(editor.CreateMemento()); Console.WriteLine("\n=== 执行一步撤销 ===" ); editor.RestoreMemento(caretaker.GetLatestMemento()); Console.WriteLine("\n=== 执行第二步撤销 ===" ); editor.RestoreMemento(caretaker.GetMemento(0 )); } catch (Exception ex) { Console.WriteLine($"执行异常:{ex.Message} " ); } } }
2.2 Python 实现(动态语言简洁实现) Python遵循“鸭子类型”,无需显式定义接口,通过类封装与属性装饰器(@property)保证备忘录的封装性,语法简洁、无冗余类型声明。依托动态特性,可灵活扩展备忘录的状态字段,无需修改核心逻辑,适用于快速开发、轻量级项目(如小型编辑器、配置工具)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 class Memento : """备忘录:存储文本编辑器的状态,仅允许原发器访问内部状态""" def __init__ (self, text_state ): self ._text_state = text_state or "" @property def text_state (self ): """供原发器读取状态的接口""" return self ._text_state class Originator : """原发器:文本编辑器,负责创建/恢复备忘录,管理自身状态""" def __init__ (self ): self ._current_text = "" def set_text (self, text ): """设置编辑器文本状态,处理空值,提升健壮性""" self ._current_text = text or "" print (f"编辑器更新状态:{self._current_text} " ) def get_text (self ): """获取当前文本状态""" return self ._current_text def create_memento (self ): """创建备忘录,捕获当前文本状态""" return Memento(self ._current_text) def restore_memento (self, memento ): """从备忘录恢复状态,校验备忘录合法性""" if not isinstance (memento, Memento): print ("警告:无效的备忘录对象,无法恢复状态" ) return self ._current_text = memento.text_state print (f"编辑器恢复状态:{self._current_text} " ) class Caretaker : """管理者:管理备忘录列表,支持多快照存储与多步撤销""" def __init__ (self, max_count=10 ): self ._mementos = [] self ._max_count = max_count def add_memento (self, memento ): """添加备忘录快照,处理空值与数量上限""" if not isinstance (memento, Memento): print ("警告:无法添加无效的备忘录" ) return if len (self ._mementos) >= self ._max_count: self ._mementos.pop(0 ) print ("提示:快照数量已达上限,移除最旧快照" ) self ._mementos.append(memento) print (f"快照添加成功,当前快照数量:{len (self._mementos)} " ) def get_latest_memento (self ): """获取最新的备忘录快照(一步撤销)""" if not self ._mementos: print ("警告:无历史快照可获取" ) return None return self ._mementos[-1 ] def get_memento (self, index ): """根据索引获取指定备忘录快照(多步撤销)""" if index < 0 or index >= len (self ._mementos): print ("警告:快照索引无效" ) return None return self ._mementos[index] if __name__ == "__main__" : try : editor = Originator() caretaker = Caretaker(max_count=5 ) editor.set_text("第1步:编写备忘录模式核心概念" ) caretaker.add_memento(editor.create_memento()) editor.set_text("第2步:梳理多语言实现思路" ) caretaker.add_memento(editor.create_memento()) editor.set_text("第3步:分析优缺点与使用场景" ) caretaker.add_memento(editor.create_memento()) print ("\n=== 执行一步撤销 ===" ) editor.restore_memento(caretaker.get_latest_memento()) print ("\n=== 执行第二步撤销 ===" ) editor.restore_memento(caretaker.get_memento(0 )) except Exception as e: print (f"执行异常:{str (e)} " )
2.3 Golang 实现(接口至上轻量实现) Go语言无类和继承,遵循“组合优于继承”原则,通过结构体封装备忘录与原发器状态,依托“小写字段”实现封装(包内可见、包外不可访问),无需额外访问修饰符。代码极简高效,贴合Go语言设计理念,适配高并发后端场景(如分布式系统配置回滚、服务状态快照)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 package mainimport ( "fmt" ) type memento struct { textState string } type Originator struct { currentText string } func (o *Originator) SetText(text string ) { if text == "" { o.currentText = "" } else { o.currentText = text } fmt.Printf("编辑器更新状态:%s\n" , o.currentText) } func (o *Originator) GetText() string { return o.currentText } func (o *Originator) CreateMemento() *memento { return &memento{textState: o.currentText} } func (o *Originator) RestoreMemento(m *memento) { if m == nil { fmt.Println("警告:备忘录不可为nil,无法恢复状态" ) return } o.currentText = m.textState fmt.Printf("编辑器恢复状态:%s\n" , o.currentText) } type Caretaker struct { mementos []*memento maxCount int } func NewCaretaker (maxCount int ) *Caretaker { if maxCount <= 0 { maxCount = 10 } return &Caretaker{ mementos: make ([]*memento, 0 , maxCount), maxCount: maxCount, } } func (c *Caretaker) AddMemento(m *memento) { if m == nil { fmt.Println("警告:无法添加空备忘录" ) return } if len (c.mementos) >= c.maxCount { c.mementos = c.mementos[1 :] fmt.Println("提示:快照数量已达上限,移除最旧快照" ) } c.mementos = append (c.mementos, m) fmt.Printf("快照添加成功,当前快照数量:%d\n" , len (c.mementos)) } func (c *Caretaker) GetLatestMemento() *memento { if len (c.mementos) == 0 { fmt.Println("警告:无历史快照可获取" ) return nil } return c.mementos[len (c.mementos)-1 ] } func (c *Caretaker) GetMemento(index int ) *memento { if index < 0 || index >= len (c.mementos) { fmt.Println("警告:快照索引无效" ) return nil } return c.mementos[index] } func main () { editor := &Originator{} caretaker := NewCaretaker(5 ) editor.SetText("第1步:编写备忘录模式核心概念" ) caretaker.AddMemento(editor.CreateMemento()) editor.SetText("第2步:梳理多语言实现思路" ) caretaker.AddMemento(editor.CreateMemento()) editor.SetText("第3步:分析优缺点与使用场景" ) caretaker.AddMemento(editor.CreateMemento()) fmt.Println("\n=== 执行一步撤销 ===" ) editor.RestoreMemento(caretaker.GetLatestMemento()) fmt.Println("\n=== 执行第二步撤销 ===" ) editor.RestoreMemento(caretaker.GetMemento(0 )) }
2.4 C++ 实现(抽象类+友元经典实现) C++通过类与友元机制实现备忘录的封装性,将原发器声明为备忘录的友元,确保只有原发器能访问备忘录的私有状态;同时通过虚析构函数与手动内存管理,避免内存泄漏。该实现兼顾灵活性与高性能,适用于底层开发、高频调用场景(如编译器撤销功能、嵌入式设备配置回滚)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 #include <iostream> #include <vector> #include <string> using namespace std;class Memento ;class Originator {private : string currentText; public : Originator () : currentText ("" ) {} void setText (const string& text) { currentText = text.empty () ? "" : text; cout << "编辑器更新状态:" << currentText << endl; } string getText () const { return currentText; } Memento* createMemento () ; void restoreMemento (Memento* m) ; }; class Memento {private : string textState; friend class Originator ; Memento (const string& state) : textState (state) {} string getTextState () const { return textState; } }; Memento* Originator::createMemento () { return new Memento (currentText); } void Originator::restoreMemento (Memento* m) { if (m == nullptr ) { cout << "警告:备忘录不可为nullptr,无法恢复状态" << endl; return ; } currentText = m->getTextState (); cout << "编辑器恢复状态:" << currentText << endl; } class Caretaker {private : vector<Memento*> mementos; int maxCount; public : Caretaker (int maxCount = 10 ) : maxCount (maxCount) {} ~Caretaker () { for (auto m : mementos) { delete m; m = nullptr ; } mementos.clear (); } void addMemento (Memento* m) { if (m == nullptr ) { cout << "警告:无法添加空备忘录" << endl; return ; } if (mementos.size () >= maxCount) { delete mementos[0 ]; mementos[0 ] = nullptr ; mementos.erase (mementos.begin ()); cout << "提示:快照数量已达上限,移除最旧快照" << endl; } mementos.push_back (m); cout << "快照添加成功,当前快照数量:" << mementos.size () << endl; } Memento* getLatestMemento () { if (mementos.empty ()) { cout << "警告:无历史快照可获取" << endl; return nullptr ; } return mementos.back (); } Memento* getMemento (int index) { if (index < 0 || index >= (int )mementos.size ()) { cout << "警告:快照索引无效" << endl; return nullptr ; } return mementos[index]; } }; int main () { try { Originator* editor = new Originator (); Caretaker* caretaker = new Caretaker (5 ); editor->setText ("第1步:编写备忘录模式核心概念" ); caretaker->addMemento (editor->createMemento ()); editor->setText ("第2步:梳理多语言实现思路" ); caretaker->addMemento (editor->createMemento ()); editor->setText ("第3步:分析优缺点与使用场景" ); caretaker->addMemento (editor->createMemento ()); cout << "\n=== 执行一步撤销 ===" << endl; editor->restoreMemento (caretaker->getLatestMemento ()); cout << "\n=== 执行第二步撤销 ===" << endl; editor->restoreMemento (caretaker->getMemento (0 )); delete editor; delete caretaker; editor = nullptr ; caretaker = nullptr ; } catch (const exception& e) { cout << "执行异常:" << e.what () << endl; } return 0 ; }
2.5 纯C语言实现(结构体+函数指针模拟实现) 纯C无面向对象特性,通过“结构体封装数据+函数指针封装行为”模拟备忘录模式的核心逻辑,依托命名约定(前缀下划线)模拟私有字段,通过函数接口控制状态的读写权限,底层可控性强、无额外依赖。适用于嵌入式、底层开发等资源受限场景,完整还原模式“封装状态、解耦管理”的核心思想。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 #include <stdio.h> #include <stdlib.h> #include <string.h> typedef struct Memento Memento ;typedef struct Originator Originator ;typedef struct Caretaker Caretaker ;typedef struct Memento { char * _text_state; } Memento; typedef struct Originator { char * current_text; Memento* (*create_memento)(Originator*); void (*restore_memento)(Originator*, Memento*); } Originator; typedef struct Caretaker { Memento** mementos; int count; int capacity; int max_count; } Caretaker; Memento* memento_create (const char * text_state) { Memento* m = (Memento*)malloc (sizeof (Memento)); if (m == NULL ) return NULL ; int len = text_state ? strlen (text_state) : 0 ; m->_text_state = (char *)malloc (len + 1 ); if (m->_text_state == NULL ) { free (m); return NULL ; } strcpy (m->_text_state, text_state ? text_state : "" ); return m; } void memento_destroy (Memento* m) { if (m == NULL ) return ; free (m->_text_state); free (m); } const char * memento_get_text_state (Memento* m) { if (m == NULL ) return "" ; return m->_text_state; } Memento* originator_create_memento (Originator* o) { if (o == NULL ) return NULL ; return memento_create(o->current_text); } void originator_restore_memento (Originator* o, Memento* m) { if (o == NULL || m == NULL ) { printf ("警告:原发器或备忘录为空,无法恢复状态\n" ); return ; } if (o->current_text != NULL ) { free (o->current_text); } const char * state = memento_get_text_state(m); int len = strlen (state); o->current_text = (char *)malloc (len + 1 ); strcpy (o->current_text, state); printf ("编辑器恢复状态:%s\n" , o->current_text); } void originator_set_text (Originator* o, const char * text) { if (o == NULL ) return ; if (o->current_text != NULL ) { free (o->current_text); } int len = text ? strlen (text) : 0 ; o->current_text = (char *)malloc (len + 1 ); strcpy (o->current_text, text ? text : "" ); printf ("编辑器更新状态:%s\n" , o->current_text); } Originator* originator_init () { Originator* o = (Originator*)malloc (sizeof (Originator)); if (o == NULL ) return NULL ; o->current_text = NULL ; o->create_memento = originator_create_memento; o->restore_memento = originator_restore_memento; originator_set_text(o, "" ); return o; } Caretaker* caretaker_init (int max_count) { Caretaker* c = (Caretaker*)malloc (sizeof (Caretaker)); if (c == NULL ) return NULL ; c->max_count = max_count <= 0 ? 10 : max_count; c->capacity = c->max_count; c->count = 0 ; c->mementos = (Memento**)malloc (sizeof (Memento*) * c->capacity); if (c->mementos == NULL ) { free (c); return NULL ; } return c; } void caretaker_add_memento (Caretaker* c, Memento* m) { if (c == NULL || m == NULL ) { printf ("警告:管理者或备忘录为空,无法添加快照\n" ); return ; } if (c->count >= c->max_count) { memento_destroy(c->mementos[0 ]); for (int i = 0 ; i < c->count - 1 ; i++) { c->mementos[i] = c->mementos[i + 1 ]; } c->count--; printf ("提示:快照数量已达上限,移除最旧快照\n" ); } c->mementos[c->count++] = m; printf ("快照添加成功,当前快照数量:%d\n" , c->count); } Memento* caretaker_get_latest_memento (Caretaker* c) { if (c == NULL || c->count == 0 ) { printf ("警告:无历史快照可获取\n" ); return NULL ; } return c->mementos[c->count - 1 ]; } Memento* caretaker_get_memento (Caretaker* c, int index) { if (c == NULL || index < 0 || index >= c->count) { printf ("警告:快照索引无效\n" ); return NULL ; } return c->mementos[index]; } void cleanup (Originator* o, Caretaker* c) { if (o != NULL ) { if (o->current_text != NULL ) { free (o->current_text); } free (o); } if (c != NULL ) { for (int i = 0 ; i < c->count; i++) { memento_destroy(c->mementos[i]); } free (c->mementos); free (c); } } int main () { Originator* editor = originator_init(); Caretaker* caretaker = caretaker_init(5 ); if (editor == NULL || caretaker == NULL ) { printf ("初始化失败,退出程序\n" ); cleanup(editor, caretaker); return -1 ; } originator_set_text(editor, "第1步:编写备忘录模式核心概念" ); caretaker_add_memento(caretaker, editor->create_memento(editor)); originator_set_text(editor, "第2步:梳理多语言实现思路" ); caretaker_add_memento(caretaker, editor->create_memento(editor)); originator_set_text(editor, "第3步:分析优缺点与使用场景" ); caretaker_add_memento(caretaker, editor->create_memento(editor)); printf ("\n=== 执行一步撤销 ===\n" ); editor->restore_memento(editor, caretaker_get_latest_memento(caretaker)); printf ("\n=== 执行第二步撤销 ===\n" ); editor->restore_memento(editor, caretaker_get_memento(caretaker, 0 )); cleanup(editor, caretaker); return 0 ; }
三、备忘录模式的优缺点 备忘录模式的核心优势的是“封装状态、灵活回滚”,但同时存在资源消耗与维护成本的权衡。实际开发中需结合业务场景,平衡设计优雅与工程落地成本,避免过度设计或滥用。
3.1 核心优点
封装性极佳 :备忘录仅允许原发器访问内部状态,外部角色(如管理者)无法直接修改或访问,完美遵循“封装原则”,保证状态数据的安全性。
状态回滚灵活 :支持多步快照的保存与恢复,可轻松实现撤销、回滚、快照备份等功能,无需修改原发器核心逻辑,适配多场景状态管理需求。
职责划分清晰 :原发器负责状态管理,备忘录负责状态存储,管理者负责备忘录生命周期管理,三者各司其职、解耦关联,符合“单一职责原则”,提升代码可维护性。
扩展性良好 :新增状态字段或扩展快照功能时,仅需修改原发器与备忘录,无需改动管理者,对现有业务逻辑侵入性低。
3.2 主要缺点
资源消耗较大 :若原发器状态字段多、快照保存频繁,会产生大量备忘录对象,占用内存资源;尤其在高频保存场景(如实时编辑器),可能引发性能瓶颈。
维护成本较高 :若原发器的状态结构发生变更(如新增/删除字段),备忘录需同步修改,管理者的存储逻辑也可能需要调整,增加维护成本。
并发安全风险 :多线程环境下,多个线程同时读写备忘录或原发器状态,可能引发线程安全问题,需额外添加锁机制,增加代码复杂度。
序列化成本高 :若需持久化备忘录(如存储到文件、数据库),需实现序列化/反序列化逻辑,尤其对于复杂状态,序列化成本较高。
四、备忘录模式的使用场景 备忘录模式的适用场景具有明确的核心前提:需要保存对象历史状态,且需支持状态回滚,同时要求不破坏对象封装性 。以下结合具体业务场景与实战案例,帮助开发者精准判断适用性,避免滥用。
4.1 核心适用场景
撤销/回滚操作场景 :最典型的场景是文本编辑器、表格软件的撤销功能,每输入一步保存一个快照,支持多步撤销;此外,数据库事务回滚、代码版本回滚也属于此类场景。
状态快照备份场景 :如游戏存档(保存角色等级、装备、进度等状态)、虚拟机快照(保存虚拟机运行状态)、系统配置快照(保存系统当前配置),支持后续恢复至指定状态。
业务流程回溯场景 :如审批流程中,保存每个节点的状态,支持回溯到任意节点重新处理;订单流程中,保存订单的状态变更记录,便于异常时回滚至正常状态。
测试场景 :自动化测试中,保存测试用例的初始状态,执行测试后恢复至初始状态,避免测试用例之间的相互影响。
4.2 不适用场景
对象状态简单、无需回滚的场景,使用备忘录模式会增加代码复杂度,直接通过变量存储状态更高效。
状态频繁变更且状态量极大的场景(如实时日志、高频数据采集),大量备忘录会占用过多内存,导致性能下降。
对象封装性要求极低,允许外部直接访问状态的场景,无需通过备忘录间接管理状态。
五、总结 备忘录模式通过“原发器-备忘录-管理者”的三元结构,优雅地解决了“状态保存与恢复”的核心痛点,其核心设计思想是在不破坏对象封装性的前提下,实现状态的安全存储与灵活回滚 。该模式的本质是“状态的隔离与管理”,让原发器专注于核心业务逻辑,将状态的存储与恢复交给备忘录和管理者,提升代码的可维护性与扩展性。
不同语言对备忘录模式的实现风格虽有显著差异,但核心逻辑高度一致:面向对象语言(C#、Python、Golang、C++)依托类、接口、友元等特性,轻松实现状态封装与访问控制,代码结构清晰;纯C语言则通过结构体+函数指针模拟面向对象特性,虽实现繁琐,但能在资源受限场景中还原模式核心价值,兼顾底层可控性。
使用备忘录模式时,需重点权衡两个核心点:一是资源消耗 ,对于高频保存、状态量大的场景,可优化为增量快照(仅保存状态变化部分)或定期清理过期快照,避免内存溢出;二是维护成本 ,若原发器状态频繁变更,需谨慎使用,避免因状态结构调整导致的大量代码修改。
总之,备忘录模式是“状态管理与回滚”场景下的最优解决方案之一,掌握其核心结构与多语言实现,能帮助开发者在实际项目中优雅处理撤销、快照、回滚等需求,平衡代码设计与工程落地成本,提升系统的健壮性与可扩展性。