Skip to content

备忘录模式

备忘录模式(Memento Pattern)是一种行为设计模式,它允许在不暴露对象实现细节的情况下保存和恢复对象的内部状态。这意味着对象可以将其状态存储在一个外部的地方(即备忘录),并在之后需要时恢复到该状态,而不会影响其封装性。

备忘录模式的主要角色

  1. Originator(原发器):需要备份和恢复其内部状态的对象。它负责创建备忘录,并使用它来存储自己的内部状态。
  2. Memento(备忘录):用于存储原发器对象的内部状态。它由原发器创建,并且只能被原发器访问以防止其他对象对其修改。
  3. Caretaker(管理者):负责保存备忘录,并确保其安全。它只知道何时保存或恢复备忘录,但不了解其内容。

在 JavaScript 中的实现

下面是一个简单的例子来说明如何在 JavaScript 中使用备忘录模式:

示例:文本编辑器的状态管理

假设你正在开发一个文本编辑器应用,用户希望能够撤销和重做他们的编辑操作。

javascript
// Memento(备忘录)
class EditorMemento {
  constructor(content) {
    this.content = content;
  }

  getContent() {
    return this.content;
  }
}

// Originator(原发器)
class TextEditor {
  constructor() {
    this.content = "";
  }

  type(words) {
    this.content += " " + words;
  }

  getContent() {
    return this.content;
  }

  save() {
    return new EditorMemento(this.content);
  }

  restore(memento) {
    this.content = memento.getContent();
  }
}

// Caretaker(管理者)
class History {
  constructor() {
    this.mementos = [];
  }

  addMemento(memento) {
    this.mementos.push(memento);
  }

  getMemento(index) {
    return this.mementos[index];
  }
}

// 使用示例
const editor = new TextEditor();
const history = new History();

editor.type("Hello");
editor.type(" world");
console.log(editor.getContent()); // 输出: " Hello world"

history.addMemento(editor.save());

editor.type(" and universe");
console.log(editor.getContent()); // 输出: " Hello world and universe"

editor.restore(history.getMemento(0));
console.log(editor.getContent()); // 输出: " Hello world"

代码解释

  • EditorMemento(备忘录):包含了一个构造函数,用来保存文本编辑器的内容。getContent 方法允许原发器恢复其状态。
  • TextEditor(原发器):代表了我们的文本编辑器。它有方法 type 来添加文本,save 方法来创建一个备忘录对象保存当前状态,以及 restore 方法来从备忘录中恢复状态。
  • History(管理者):维护了一个备忘录对象的列表,提供添加和获取备忘录的方法。这里仅作为简单演示,实际应用中可能需要更复杂的管理逻辑,比如支持撤销多次等。

应用场景

备忘录模式适用于以下几种情况:

  • 当需要保存一个对象的状态以便稍后恢复(如撤销/重做功能)。
  • 当直接访问对象的成员变量会破坏对象的封装性时,通过备忘录可以在不影响封装的情况下保存状态。
  • 当需要记录对象的历史状态以便后续回滚时。

通过使用备忘录模式,可以在不破坏对象封装性的前提下保存和恢复对象的状态,这为处理复杂的状态管理问题提供了有效解决方案。然而,在使用备忘录模式时需要注意性能问题,特别是当保存大量状态或者状态本身非常大时。

Released under the MIT License.