5.6 MEMENTO(备忘录)—对象行为型模式

2018-01-06  本文已影响28人  10xjzheng
1 意图

在不破坏封装性的前提下,捕获了一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可以将该对象恢复到原先保存的状态。

2 别名

Token

3 动机

有时有必要记录一个对象的内部状态。为了运行用户取消不确定的操作或从错误中恢复过来,需要实现检查点和取消机制,而要实现这些机制,你必须事先将状态信息保存在某处,这样才能将对象恢复到它们先前的状态。但是对象通常封装了其部分或所有的状态信息,使得其状态不能被其他对象访问,也就不可能在该对象之外保存起状态。而暴露其内部状态又将违反封装的原则,可能有损应用的可靠性和可扩展性。

例如,考虑一个图形编辑器,它支持图形对象间的连线。用户可用一条直线连接两个矩形,而当用户移动任意一个矩形时,这两个矩形仍能保持连接。在移动过程中,编辑器自动伸展这条直线保持该连接。


image.png

一个众所周知的保持对象间连接关系的方法是使用一个约束解释系统。我们可将这一功能封装在一个ConstaintSolver对象中。ConstaintSolver在连接生成时, 记录这些连接并产生描述它们的数学方程。当用户生成一个连接或修改图形时,ConstaintSolver就求解这些方程。并根据它的计算结果重新调整图形,使各个对象保持正确的连接。

在这一应用中,支持取消操并不象看起那么容易。一个显而易见的方法是,每次移动时保存移动的距离,而在取消这次移动时该对象移回相等的距离。然而 , 这不能保证所有的对象都会出现在它们原先出现的地方。设想在移动过程中某连接中有一些松弛。在这种情况下 , 简单地将矩形移回它原来的位置并不一定能得到预想的结果。


image.png

一般来说, ConstraintSolver的公共接口可能不足以精确地逆转它对其他对象的作用。为重建先前的状态,取消操作机制必须与ConstraintSolver更紧密的结合 , 但我们同时也应避免将ConstraintSolver的内部暴露给取消操作机制。

我们可用备忘录 ( Memento )模式解决这一问题。一个备忘录 (Memento)是一个对象 , 它存储另一个对象在某个瞬间的内部状态,而后者称为备忘录的原发器。当需要设置原发器的检查点时,取消操作机制会向原发器请求一个备忘录。原发器用描述当前状态的信息初始化该备忘录。只有原发器可以向备忘录中存取信息,备忘录对其他的对象 “不可见”。

在刚才讨论的图形编辑器的例子中,ConstraintSolver可作为一个原发器,下面的事件序列描述了取消操作的过程:

4 适用性

在以下情况下使用备忘录模式:

5 结构
image.png
6 参与者
7 协作

管理器向原发器请求一个备忘录,保存一段时间后,将其送回给原发器,如下图的交互图所示:


image.png

有时管理者不会将备忘录返回给原发器,因为原发器可能根本不需要推到先前的状态,备忘录是被动的,只有创建备忘录的原发器会对它的状态进行赋值和检索。

8 效果

备忘录模式有以下效果:

9 实现

下面是当实现备忘录模式时应考虑的两个问题 :

10 代码示例

github地址

上一篇 下一篇

猜你喜欢

热点阅读