备忘录模式(Memento Pattern)详解

前一篇文章解锁时光机用到了备忘录模式,那么什么是备忘录模式?

备忘录模式是一种行为型设计模式,它的核心思想是在不暴露对象内部细节的情况下,捕获并保存一个对象的内部状态,以便在将来可以恢复到这个状态

这个模式就像一个"时光机",能够让你在程序运行时记录下某个时刻的状态,并在需要时"穿越"回去。

核心角色

备忘录模式通常包含三个主要角色:

  1. 发起人(Originator)

    • 这是需要被保存状态的对象。
    • 它负责创建一个备忘录(Memento),来保存自己的当前状态。
    • 它也能够使用备忘录来恢复到之前的状态。
    • 在我们的 React 例子中,reducer 函数和其中的 state 对象就是发起人。它能创建和恢复状态。
  2. 备忘录(Memento)

    • 这是用于存储发起人内部状态的快照对象。
    • 它提供一个受限的接口,只允许发起人访问其内部状态。外部对象(比如 caretaker)无法直接修改备忘录的内容,只能将其作为"黑盒子"传递。
    • 在我们的 React 例子中,pastfuture 数组中的每一个 present 值,就是一个备忘录。它是一个简单的数值,不需要复杂的对象来封装。
  3. 管理者(Caretaker)

    • 负责保存和管理备忘录。
    • 它不知道备忘录内部的具体细节,只知道备忘录是从发起人那里来的,并能在需要时将它还给发起人。
    • 它不能对备忘录的内容进行任何操作,只能存储和检索。
    • 在我们的 React 例子中,state 对象中的 pastfuture 数组就是管理者reducer 函数负责将备忘录(即状态值)放入或取出这些数组。

工作流程

  1. 保存状态 :发起人(Originator)在需要时,创建一个备忘录(Memento),将自己的当前状态保存进去。然后将这个备忘录交给管理者(Caretaker)。
  2. 恢复状态 :当需要恢复时,管理者(Caretaker)将之前保存的备忘录交给发起人(Originator)。发起人通过备忘录中的信息,将自己的状态恢复到之前的样子。

备忘录模式与代码示例

现在,让我们把这些角色对应到代码中,一切就变得清晰了:

  • 发起人(Originator) : state 对象中的 present 值。它代表了当前的核心状态。
  • 备忘录(Memento) : pastfuture 数组中的每一个数值。每个数值都是一个"状态快照"。
  • 管理者(Caretaker) : state 对象中的 pastfuture 数组。它们负责存储这些状态快照。

具体实现流程:

  1. Increment 操作

    • Originatorpresent)的状态即将改变。
    • Originator 告诉 Caretakerpast 数组),"我马上要变了,这是我现在的样子,你帮我存一下。"
    • Caretaker 将当前的 present[...past, present] 存入 past 数组。
  2. Undo 操作

    • Caretakerpast 数组)将最后一个备忘录(past.at(-1))交给 Originator
    • Originator 接收这个备忘录,并将其恢复为自己的状态(present: past.at(-1))。
    • 同时,Originator 将当前状态作为新的备忘录,交给另一个 Caretakerfuture 数组),以便重做。

为什么这种模式更优越?

备忘录模式的优点在于它实现了解耦 。管理者(past/future 数组)和发起人(present 值)之间只需要知道如何存取备忘录,而不需要知道备忘录内部的具体结构或如何改变状态。这意味着你可以轻松地改变 incrementdecrement 的逻辑,而 undoredo 的逻辑完全不需要改动。

这就是为什么代码二的设计如此优雅和可扩展。它不关心"如何"改变,只关心"改变前"和"改变后"的状态是什么,并将这些状态作为备忘录保存起来。

相关推荐
Swift社区6 小时前
React Navigation 生命周期完整心智模型
前端·react.js·前端框架
若梦plus6 小时前
从微信公众号&小程序的SDK剖析JSBridge
前端
用泥种荷花6 小时前
Python环境安装
前端
Light606 小时前
性能提升 60%:前端性能优化终极指南
前端·性能优化·图片压缩·渲染优化·按需拆包·边缘缓存·ai 自动化
Jimmy7 小时前
年终总结 - 2025 故事集
前端·后端·程序员
烛阴7 小时前
C# 正则表达式(2):Regex 基础语法与常用 API 全解析
前端·正则表达式·c#
roman_日积跬步-终至千里7 小时前
【人工智能导论】02-搜索-高级搜索策略探索篇:从约束满足到博弈搜索
java·前端·人工智能
GIS之路7 小时前
GIS 数据转换:使用 GDAL 将 TXT 转换为 Shp 数据
前端
多看书少吃饭7 小时前
从Vue到Nuxt.js
前端·javascript·vue.js
前端一小卒7 小时前
从 v5 到 v6:这次 Ant Design 升级真的香
前端·javascript