Python 备忘录模式(Memento)
备忘录模式是一种行为设计模式,它允许在不破坏封装性的前提下,捕获并保存一个对象的内部状态,以便在需要时能够恢复到之前的状态。
想象一下你在玩一个游戏,游戏提供了"存档"功能。你可以随时保存当前游戏进度,如果后续游戏失败或者想重新尝试某个关卡,就可以读取之前的存档。备忘录模式就是实现这种"存档-读档"功能的编程解决方案。
为什么需要备忘录模式?
应用场景
- 文本编辑器:实现撤销(Undo)和重做(Redo)功能
- 游戏开发:保存游戏进度和状态
- 图形软件:支持操作历史记录
- 事务处理:在操作失败时回滚到之前的状态
解决的问题
- 需要保存对象状态,但又不想暴露对象内部细节
- 提供状态恢复机制,支持"后悔药"功能
- 保持对象的封装性,避免状态保存逻辑与业务逻辑混杂
备忘录模式的核心组件
备忘录模式包含三个主要角色:
1. 发起人(Originator)
- 需要保存状态的对象
- 创建备忘录来记录当前状态
- 使用备忘录恢复之前的状态
2. 备忘录(Memento)
- 存储发起人对象的内部状态
- 防止发起人之外的对象访问备忘录内容
3. 管理者(Caretaker)
- 负责保存备忘录
- 不能对备忘录的内容进行操作或检查

Python 实现备忘录模式
让我们通过一个文本编辑器的例子来具体实现备忘录模式。
基础实现
实例
class TextEditorMemento:
"""备忘录类 - 保存文本编辑器的状态"""
def __init__(self, content):
self._content = content
def get_content(self):
"""获取保存的内容"""
return self._content
class TextEditor:
"""发起人类 - 文本编辑器"""
def __init__(self):
self._content = ""
def write(self, text):
"""写入文本"""
self._content += text
def get_content(self):
"""获取当前内容"""
return self._content
def save(self):
"""创建备忘录 - 保存当前状态"""
return TextEditorMemento(self._content)
def restore(self, memento):
"""恢复状态 - 从备忘录读取"""
self._content = memento.get_content()
class HistoryManager:
"""管理者类 - 历史记录管理器"""
def __init__(self):
self._mementos = []
def push(self, memento):
"""保存备忘录"""
self._mementos.append(memento)
def pop(self):
"""获取最新的备忘录"""
if self._mementos:
return self._mementos.pop()
return None
"""备忘录类 - 保存文本编辑器的状态"""
def __init__(self, content):
self._content = content
def get_content(self):
"""获取保存的内容"""
return self._content
class TextEditor:
"""发起人类 - 文本编辑器"""
def __init__(self):
self._content = ""
def write(self, text):
"""写入文本"""
self._content += text
def get_content(self):
"""获取当前内容"""
return self._content
def save(self):
"""创建备忘录 - 保存当前状态"""
return TextEditorMemento(self._content)
def restore(self, memento):
"""恢复状态 - 从备忘录读取"""
self._content = memento.get_content()
class HistoryManager:
"""管理者类 - 历史记录管理器"""
def __init__(self):
self._mementos = []
def push(self, memento):
"""保存备忘录"""
self._mementos.append(memento)
def pop(self):
"""获取最新的备忘录"""
if self._mementos:
return self._mementos.pop()
return None
完整示例代码
实例
# 备忘录模式完整示例
def memo_pattern_demo():
# 创建文本编辑器和历史管理器
editor = TextEditor()
history = HistoryManager()
print("=== 文本编辑器备忘录模式演示 ===\n")
# 第一次编辑并保存
editor.write("Hello, ")
history.push(editor.save())
print(f"当前内容: {editor.get_content()}")
print("✅ 已保存状态\n")
# 第二次编辑并保存
editor.write("World!")
history.push(editor.save())
print(f"当前内容: {editor.get_content()}")
print("✅ 已保存状态\n")
# 第三次编辑但不保存
editor.write(" This is new text.")
print(f"当前内容: {editor.get_content()}")
print("❌ 未保存当前编辑\n")
# 撤销操作 - 恢复到上一次保存的状态
memento = history.pop()
if memento:
editor.restore(memento)
print(f"撤销后内容: {editor.get_content()}")
print("↩️ 已撤销到上一个保存点\n")
# 再次撤销
memento = history.pop()
if memento:
editor.restore(memento)
print(f"再次撤销后内容: {editor.get_content()}")
print("↩️ 已撤销到最初状态")
# 运行演示
if __name__ == "__main__":
memo_pattern_demo()
def memo_pattern_demo():
# 创建文本编辑器和历史管理器
editor = TextEditor()
history = HistoryManager()
print("=== 文本编辑器备忘录模式演示 ===\n")
# 第一次编辑并保存
editor.write("Hello, ")
history.push(editor.save())
print(f"当前内容: {editor.get_content()}")
print("✅ 已保存状态\n")
# 第二次编辑并保存
editor.write("World!")
history.push(editor.save())
print(f"当前内容: {editor.get_content()}")
print("✅ 已保存状态\n")
# 第三次编辑但不保存
editor.write(" This is new text.")
print(f"当前内容: {editor.get_content()}")
print("❌ 未保存当前编辑\n")
# 撤销操作 - 恢复到上一次保存的状态
memento = history.pop()
if memento:
editor.restore(memento)
print(f"撤销后内容: {editor.get_content()}")
print("↩️ 已撤销到上一个保存点\n")
# 再次撤销
memento = history.pop()
if memento:
editor.restore(memento)
print(f"再次撤销后内容: {editor.get_content()}")
print("↩️ 已撤销到最初状态")
# 运行演示
if __name__ == "__main__":
memo_pattern_demo()
运行结果:

高级应用:支持多种状态的备忘录
在实际应用中,我们可能需要保存对象的多个属性。下面是一个更复杂的例子:
实例
import datetime
import json
class GameStateMemento:
"""游戏状态备忘录"""
def __init__(self, level, score, player_health, inventory):
self._state = {
'level': level,
'score': score,
'player_health': player_health,
'inventory': inventory.copy(), # 创建副本避免引用问题
'timestamp': datetime.datetime.now().isoformat()
}
def get_state(self):
"""获取完整状态"""
return self._state.copy()
def get_timestamp(self):
"""获取保存时间"""
return self._state['timestamp']
class Game:
"""游戏类 - 发起人"""
def __init__(self):
self.level = 1
self.score = 0
self.player_health = 100
self.inventory = ['sword', 'potion']
def play(self, level_increase=1, score_increase=100, health_change=0, new_item=None):
"""模拟游戏进程"""
self.level += level_increase
self.score += score_increase
self.player_health += health_change
if new_item and new_item not in self.inventory:
self.inventory.append(new_item)
# 生命值不能为负
self.player_health = max(0, self.player_health)
def display_status(self):
"""显示当前状态"""
status = f"""
🎮 游戏状态:
关卡: {self.level}
分数: {self.score}
生命值: {self.player_health}
背包: {', '.join(self.inventory)}
"""
print(status)
def save_game(self):
"""保存游戏状态"""
return GameStateMemento(
self.level,
self.score,
self.player_health,
self.inventory
)
def load_game(self, memento):
"""加载游戏状态"""
state = memento.get_state()
self.level = state['level']
self.score = state['score']
self.player_health = state['player_health']
self.inventory = state['inventory']
class SaveManager:
"""存档管理器"""
def __init__(self):
self.saves = {}
def create_save(self, save_name, memento):
"""创建存档"""
self.saves[save_name] = memento
print(f"💾 存档 '{save_name}' 创建成功!")
def load_save(self, save_name):
"""加载存档"""
if save_name in self.saves:
print(f"🔄 正在加载存档 '{save_name}'...")
return self.saves[save_name]
else:
print(f"❌ 存档 '{save_name}' 不存在!")
return None
def list_saves(self):
"""列出所有存档"""
if not self.saves:
print("📁 暂无存档")
return
print("\n📋 存档列表:")
for name, memento in self.saves.items():
timestamp = memento.get_timestamp()
print(f" - {name} (保存于: {timestamp})")
# 高级示例演示
def advanced_memo_demo():
print("=== 游戏存档系统演示 ===\n")
game = Game()
save_manager = SaveManager()
# 初始状态
print("🎯 开始新游戏:")
game.display_status()
# 游戏进程
print("🚀 进行游戏...")
game.play(level_increase=2, score_increase=500, new_item='shield')
game.display_status()
# 保存第一个存档
save_manager.create_save("第一关通关", game.save_game())
# 继续游戏
print("⚔️ 继续冒险...")
game.play(level_increase=1, score_increase=200, health_change=-30, new_item='magic_wand')
game.display_status()
# 保存第二个存档
save_manager.create_save("第二关开始", game.save_game())
# 显示存档列表
save_manager.list_saves()
# 加载第一个存档
print("\n⏪ 回到第一关通关状态:")
first_save = save_manager.load_save("第一关通关")
if first_save:
game.load_game(first_save)
game.display_status()
# 运行高级示例
if __name__ == "__main__":
advanced_memo_demo()
import json
class GameStateMemento:
"""游戏状态备忘录"""
def __init__(self, level, score, player_health, inventory):
self._state = {
'level': level,
'score': score,
'player_health': player_health,
'inventory': inventory.copy(), # 创建副本避免引用问题
'timestamp': datetime.datetime.now().isoformat()
}
def get_state(self):
"""获取完整状态"""
return self._state.copy()
def get_timestamp(self):
"""获取保存时间"""
return self._state['timestamp']
class Game:
"""游戏类 - 发起人"""
def __init__(self):
self.level = 1
self.score = 0
self.player_health = 100
self.inventory = ['sword', 'potion']
def play(self, level_increase=1, score_increase=100, health_change=0, new_item=None):
"""模拟游戏进程"""
self.level += level_increase
self.score += score_increase
self.player_health += health_change
if new_item and new_item not in self.inventory:
self.inventory.append(new_item)
# 生命值不能为负
self.player_health = max(0, self.player_health)
def display_status(self):
"""显示当前状态"""
status = f"""
🎮 游戏状态:
关卡: {self.level}
分数: {self.score}
生命值: {self.player_health}
背包: {', '.join(self.inventory)}
"""
print(status)
def save_game(self):
"""保存游戏状态"""
return GameStateMemento(
self.level,
self.score,
self.player_health,
self.inventory
)
def load_game(self, memento):
"""加载游戏状态"""
state = memento.get_state()
self.level = state['level']
self.score = state['score']
self.player_health = state['player_health']
self.inventory = state['inventory']
class SaveManager:
"""存档管理器"""
def __init__(self):
self.saves = {}
def create_save(self, save_name, memento):
"""创建存档"""
self.saves[save_name] = memento
print(f"💾 存档 '{save_name}' 创建成功!")
def load_save(self, save_name):
"""加载存档"""
if save_name in self.saves:
print(f"🔄 正在加载存档 '{save_name}'...")
return self.saves[save_name]
else:
print(f"❌ 存档 '{save_name}' 不存在!")
return None
def list_saves(self):
"""列出所有存档"""
if not self.saves:
print("📁 暂无存档")
return
print("\n📋 存档列表:")
for name, memento in self.saves.items():
timestamp = memento.get_timestamp()
print(f" - {name} (保存于: {timestamp})")
# 高级示例演示
def advanced_memo_demo():
print("=== 游戏存档系统演示 ===\n")
game = Game()
save_manager = SaveManager()
# 初始状态
print("🎯 开始新游戏:")
game.display_status()
# 游戏进程
print("🚀 进行游戏...")
game.play(level_increase=2, score_increase=500, new_item='shield')
game.display_status()
# 保存第一个存档
save_manager.create_save("第一关通关", game.save_game())
# 继续游戏
print("⚔️ 继续冒险...")
game.play(level_increase=1, score_increase=200, health_change=-30, new_item='magic_wand')
game.display_status()
# 保存第二个存档
save_manager.create_save("第二关开始", game.save_game())
# 显示存档列表
save_manager.list_saves()
# 加载第一个存档
print("\n⏪ 回到第一关通关状态:")
first_save = save_manager.load_save("第一关通关")
if first_save:
game.load_game(first_save)
game.display_status()
# 运行高级示例
if __name__ == "__main__":
advanced_memo_demo()
备忘录模式的优缺点
优点
- 封装性保护:不暴露对象内部状态,保持封装性
- 简化发起人:将状态保存逻辑从业务逻辑中分离
- 易于实现恢复:提供简单的状态恢复机制
- 支持多次撤销:可以保存多个时间点的状态
缺点
- 内存消耗:如果状态很大或保存频繁,会消耗大量内存
- 管理者开销:需要额外的类来管理备忘录
- 生命周期管理:需要妥善处理备忘录的创建和销毁
最佳实践和注意事项
1. 内存优化策略
实例
# 限制保存的历史记录数量
class LimitedHistoryManager:
def __init__(self, max_size=10):
self._mementos = []
self._max_size = max_size
def push(self, memento):
if len(self._mementos) >= self._max_size:
# 移除最旧的记录
self._mementos.pop(0)
self._mementos.append(memento)
class LimitedHistoryManager:
def __init__(self, max_size=10):
self._mementos = []
self._max_size = max_size
def push(self, memento):
if len(self._mementos) >= self._max_size:
# 移除最旧的记录
self._mementos.pop(0)
self._mementos.append(memento)
2. 处理复杂对象状态
对于包含复杂引用的对象,需要确保备忘录创建的是深拷贝:
实例
import copy
class ComplexMemento:
def __init__(self, complex_state):
# 使用深拷贝避免引用问题
self._state = copy.deepcopy(complex_state)
class ComplexMemento:
def __init__(self, complex_state):
# 使用深拷贝避免引用问题
self._state = copy.deepcopy(complex_state)
3. 选择性保存
不是所有状态都需要保存,可以选择只保存重要的属性:
实例
def create_selective_memento(self):
"""选择性保存重要状态"""
important_state = {
'essential_data': self.essential_data,
'critical_settings': self.critical_settings
# 忽略临时数据和缓存
}
return SelectiveMemento(important_state)
"""选择性保存重要状态"""
important_state = {
'essential_data': self.essential_data,
'critical_settings': self.critical_settings
# 忽略临时数据和缓存
}
return SelectiveMemento(important_state)
实际应用场景
1. 图形编辑器
实例
class GraphicEditor:
def save_state(self):
return GraphicMemento(
self.selected_shapes.copy(),
self.canvas_state,
self.view_settings
)
def save_state(self):
return GraphicMemento(
self.selected_shapes.copy(),
self.canvas_state,
self.view_settings
)
2. 配置管理器
实例
class ConfigManager:
def backup_config(self):
return ConfigMemento(
self.current_settings.copy(),
self.user_preferences
)
def backup_config(self):
return ConfigMemento(
self.current_settings.copy(),
self.user_preferences
)
3. 事务操作
实例
class DatabaseTransaction:
def create_checkpoint(self):
return TransactionMemento(
self.connection_state,
self.pending_operations.copy()
)
def create_checkpoint(self):
return TransactionMemento(
self.connection_state,
self.pending_operations.copy()
)
总结
备忘录模式是一个强大而实用的设计模式,它为我们提供了一种优雅的状态保存和恢复机制。通过将状态保存逻辑与业务逻辑分离,它不仅保持了代码的整洁性,还增强了系统的可维护性。
关键要点:
- 备忘录模式的核心是"保存-恢复"机制
- 三个核心角色各司其职,职责分明
- 在实际使用中要注意内存管理和状态选择
- 适用于需要撤销、重做或状态回滚的场景
点我分享笔记