备忘录模式(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 的逻辑完全不需要改动。

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

相关推荐
时雨__10 分钟前
利用AndVX6开发流程图——问题总结
前端
云枫晖33 分钟前
深入浅出npm:现代JavaScript项目基石
前端·javascript·node.js
不一样的少年_36 分钟前
你家孩子又偷玩网页游戏? 试试这个防沉迷工具
前端·javascript·浏览器
春秋半夏36 分钟前
vue2二次封装el-select支持collapse-tags-tooltip
前端
昔人'40 分钟前
css`scrollbar-gutter`防止滚动条可见性变化时发生布局偏移
前端·css
掘金安东尼42 分钟前
前端周刊第436期(2025年10月13日–10月19日)
前端·javascript·github
小叫花子1 小时前
用 UniApp 开发微信小程序蓝牙通信功能
前端
勤奋菲菲1 小时前
深入理解HTML文本标签:构建网页内容的基础
前端·html
昔人'1 小时前
html`<mark>`
前端·javascript·html