C++备忘录模式:优雅实现对象状态保存与恢复

C++备忘录模式:优雅实现对象状态保存与恢复

C++备忘录模式:优雅实现对象状态保存与恢复

引言

在软件开发中,我们经常需要实现撤销操作、历史记录或状态回滚等功能。备忘录模式(Memento Pattern)正是为解决这类问题而生的设计模式。本文将深入探讨备忘录模式在C++中的实现与应用,帮助开发者掌握这一强大的设计工具。

备忘录模式概述

备忘录模式是一种行为设计模式,它允许在不破坏封装性的前提下捕获并外部化一个对象的内部状态,以便以后可以将该对象恢复到原先保存的状态【1†source】。该模式特别适合需要实现撤销操作、历史记录或快照功能的场景【1†source】【2†source】。

核心角色解析

1. Originator(发起人)

Originator是需要保存状态的对象,它:

  • 负责创建备忘录并记录当前状态
  • 可以使用备忘录恢复之前的状态
  • 知道如何正确保存和恢复自身状态【1†source】【2†source】

2. Memento(备忘录)

Memento是存储Originator状态的对象,特点包括:

  • 存储Originator的内部状态
  • 提供两个接口:宽接口(Originator使用)和窄接口(其他对象使用)【1†source】
  • 确保状态的封装性不被破坏

3. Caretaker(管理者)

Caretaker负责管理备忘录,其职责是:

  • 保存备忘录对象
  • 不操作备忘录内容
  • 只能通过窄接口与备忘录交互【1†source】

设计原则体现

备忘录模式很好地体现了多个面向对象设计原则:

  1. 单一职责原则:将状态保存的职责从Originator中分离出来【3†source】【7†source】,使Originator可以专注于核心业务逻辑【3†source】。
  2. 开闭原则:不需要修改Originator类就能扩展状态保存功能【3†source】,通过新增备忘录类实现这一扩展【3†source】。
  3. 迪米特法则:Caretaker不直接操作Memento内部细节【3†source】【6†source】,有效降低了系统耦合度【6†source】。

C++实现示例

#include<iostream>#include<string>#include<vector>// 备忘录类classMemento{private: std::string state;// 只有Originator可以访问私有成员friendclassOriginator;Memento(const std::string& s):state(s){} std::string GetState()const{return state;}};// 发起人类classOriginator{private: std::string state;public:voidSetState(const std::string& s){ std::cout <<"设置状态: "<< s << std::endl; state = s;} Memento*CreateMemento(){returnnewMemento(state);}voidRestoreFromMemento(const Memento* m){ state = m->GetState(); std::cout <<"恢复状态: "<< state << std::endl;}};// 管理者类classCaretaker{private: std::vector<Memento*> mementos; Originator* originator;public:Caretaker(Originator* orig):originator(orig){}~Caretaker(){for(auto m : mementos)delete m;}voidSave(){ mementos.push_back(originator->CreateMemento());}voidUndo(){if(mementos.empty())return; Memento* m = mementos.back(); originator->RestoreFromMemento(m); mementos.pop_back();delete m;}};// 使用示例intmain(){ Originator originator; Caretaker caretaker(&originator); originator.SetState("状态1"); caretaker.Save(); originator.SetState("状态2"); caretaker.Save(); originator.SetState("状态3");// 执行撤销 caretaker.Undo();// 恢复到状态2 caretaker.Undo();// 恢复到状态1return0;}

典型应用场景

备忘录模式在以下场景中特别有用:

  1. 撤销/重做功能:如文本编辑器中的撤销操作【1†source】【2†source】
  2. 事务回滚系统:数据库操作的事务管理【1†source】【5†source】
  3. 游戏存档系统:保存和恢复游戏进度【1†source】【2†source】
  4. 配置管理:保存和恢复系统配置状态

高级特性与优化

1. 增量备忘录

对于状态变化不大的场景,可以只保存变化部分【1†source】,这能显著减少内存消耗【1†source】。

2. 序列化支持

通过序列化技术,可以将备忘录状态持久化存储【2†source】,如保存到文件或数据库中【1†source】。

3. 线程安全考虑

在多线程环境中使用时【2†source】,需要添加适当的同步机制来保证状态的一致性【1†source】。

与其他模式的协作

备忘录模式常与其他设计模式配合使用:

  1. 命令模式:实现可撤销的操作【1†source】【2†source】
  2. 原型模式:通过克隆对象状态来优化备忘录创建【1†source】【2†source】
  3. 状态模式:保存不同状态配置【1†source】【2†source】

注意事项

  1. 内存消耗:对于大对象状态,需考虑内存使用情况【8†source】,可能影响系统性能【1†source】
  2. C++内存管理:特别注意指针和内存泄漏问题【1†source】【2†source】
  3. 替代方案:原型模式有时可作为更简单的替代方案【2†source】

总结

备忘录模式是面向对象设计原则的优秀实践【9†source】,通过状态封装实现了灵活的回滚机制【1†source】【2†source】。合理使用该模式可以显著提高系统的可维护性和扩展性【3†source】【7†source】。在C++中实现时,需要特别注意内存管理和线程安全等问题。掌握备忘录模式将帮助开发者构建更加强大、灵活的系统。

Read more

程序员的附加技能:Git 使用从入门到精通

程序员的附加技能:Git 使用从入门到精通

文章目录 * 1. Git 基础概念 * 核心概念 * 文件状态生命周期 * 2. 安装与配置 * 安装 Git * 基础配置 * 重要配置文件位置 * 3. 仓库操作 * 初始化仓库 * 仓库结构 * 4. 基础工作流 * 标准工作流程 * 提交规范示例 * 5. 分支管理 * 分支操作 * 分支策略示例 * 变基(Rebase)与合并(Merge) * 6. 远程协作 * 远程仓库操作 * 协作工作流 * 解决冲突 * 7. 高级操作 * 贮藏变更 * 二分查找(定位问题提交) * 重写历史 * 大文件存储(LFS) * 8. 撤销与恢复 * 撤销工作区修改 * 撤销暂存区文件 * 撤销提交 * 恢复删除的文件 * 9. 子模块与工作树 * 子模块

By Ne0inhk
爆肝 2 天,用 GLM5 开发了 OpenClaw 接入微信 bot,已开源!

爆肝 2 天,用 GLM5 开发了 OpenClaw 接入微信 bot,已开源!

这是苍何的第 493 篇原创! 大家好,我是苍何。 OpenClaw,这个 GitHub 上 18 万 Star 的怪物级开源项目,你们应该都听过了吧? 飞书能接、钉钉能接、企业微信能接、QQ 能接、Discord 能接…… 但偏偏最多人用的「微信个人号」,它不支持。 我翻遍了 GitHub、掘金、知乎,找到的方案要么是企业微信绕一圈,要么是用微信 Web 协议搞,动不动就封号。 说实话,这谁顶得住? 天天在微信上跟朋友聊天、在群里吹水,结果想接个 OpenClaw 都这么费劲? 麻了。 于是我决定自己干。 「爆肝 2 天,我把 OpenClaw 接入了微信个人号,并且已经开源了。」 地址:

By Ne0inhk
【2026 最新】下载安装 Git 详细教程 (Windows)

【2026 最新】下载安装 Git 详细教程 (Windows)

一、下载Git 1.下载网址:Git - Downloads (git-scm.com) https://git-scm.com/downloads 网盘链接: 通过百度网盘分享的文件:Git-2.50.1-64-bit.exe 链接:https://pan.baidu.com/s/1lRrAifTBtCYXAA4qr31UkA?pwd=dy6bhttps://pan.baidu.com/s/1lRrAifTBtCYXAA4qr31UkA?pwd=dy6b提取码:dy6b 2.等下载完成,找到下载文件的位置,双击打开安装向导 二、安装Git 1.许可声明点击Next 2.选择安装位置 记住这个位置接下来要用到 3.选择组件 勾选添加在桌面上,

By Ne0inhk
【代码管理】在本地使用github和gitee之后,可能存在冲突,导致再次提交代码时提示Couldn‘t connect to server

【代码管理】在本地使用github和gitee之后,可能存在冲突,导致再次提交代码时提示Couldn‘t connect to server

大家好,我是全栈小5,欢迎来到《小5讲堂》。 这是《源代码管理工具》系列文章,每篇文章将以博主理解的角度展开讲解。 温馨提示:博主能力有限,理解水平有限,若有不对之处望指正! 目录 * 前言 * 错误提示 * 解决方案 * 方案1:临时关闭 Git 的代理设置(推荐先尝试) * 方案2:检查并启动代理服务 * 方案3:直接使用命令行取消代理后克隆 * 方案4:检查环境变量 * 针对 Windows 系统的具体操作 * 方法1:使用 Git Bash 或命令提示符 * 方法2:检查全局 Git 配置 * 验证解决方案 * 如果您确实需要代理 * 为什么会冲突 * 1. 代理配置冲突 * 问题原因: * 典型症状: * 2. 认证信息冲突 * SSH 密钥冲突:

By Ne0inhk