设计模式之Memento模式(备忘录、纪念品模式)

239 阅读3分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第8天,点击查看活动详情

简介:

Memento模式 :通过引入表示实例状态的角色,可以在保存和恢复实例时有效地防止对象的封装性遭到破坏;广泛运用在快照功能之中。

关键角色:

Originator(原发器): 它是一个普通类,可以创建一个备忘录,并存储它的当前内部状态,也可以使用备忘录来恢复其内部状态,一般将需要保存内部状态的类设计为原发器。

Memento(备忘录): 存储原发器的内部状态,根据原发器来决定保存哪些内部状态。备忘录的设计一般可以参考原发器的设计,根据实际需要确定备忘录类中的属性。需要注意的是,除了原发器本身与负责人的类之外,备忘录对象不能直接供其他类使用,原发器的设计在不同的编程语言中实现机制会有所不同。

Caretaker(负责人): 负责人又称为管理者,它负责保存备忘录,但是不能对备忘录的内容进行操作或检查。在负责人类中可以存储一个或多个备忘录对象,它只负责存储对象,而不能修改对象,也无须指定对象的实现细节。

UML diagram.jpeg

示例代码:

// Memento 备忘录对象 只供原发器使用 提供状态提取方法
var Memento = function (state) {
  var _state = state;
  this.getState = function () {
    return _state;
  }
}
// Originator 原发器
var Originator = function () {
  var _state;
  this.setState = function (state) {
    _state = state;
  }
  this.getState = function () {
    return _state;
  }
  // saveStateToMemento 创建一个备忘录 存储当前状态
  this.saveStateToMemento = function () {
    return new Memento(_state);
  }
  this.getStateFromMemento = function (memento) {
    _state = memento.getState();
  }
}
// 负责人 负责保存备忘录 但是不能对备忘录内容进行操作或检查
var CareTaker = function () {
  var _mementoList = [];
  this.add = function (memento) {
    _mementoList.push(memento);
  }
  this.get = function (index) {
    return _mementoList[index];
  }
}


var originator = new Originator();
var careTaker = new CareTaker();
originator.setState("State 1");
originator.setState("State 2");
careTaker.add(originator.saveStateToMemento());
originator.setState("State 3");
careTaker.add(originator.saveStateToMemento());
originator.setState("State 4");


console.log("当前状态: " + originator.getState());
// 当前状态: State 4
originator.getStateFromMemento(careTaker.get(0));
console.log("恢复第一次保存状态: " + originator.getState());
// 恢复第一次保存状态: State 2
originator.getStateFromMemento(careTaker.get(1));
console.log("恢复第二次保存: " + originator.getState());
// 恢复第二次保存: State 3

应用场景:

日常场景:

浏览器word文档的上一步与下一步ctrl+z与ctrl+shift+z悔棋机制代码版本回滚游戏存档。

由于在备忘录中存储的是原发器的中间状态,因此需要防止原发器以外的其他对象访问备忘录,特别是不允许其他对象来修改备忘录。在使用备忘录模式时,首先应该存在一个原发器类Originator,在真实业务中,原发器类是一个具体的业务类,它包含一些用于存储成员数据的属性。

具体业务:

用户的每一步都能撤销与恢复(打开弹框-关闭弹框、填写表单-清空表单、提交当前表单的请求-删除当前表单记录的请求)。

缺点:

备忘录模式对资源的消耗过大; 会额外占用磁盘、内存等资源。