备忘录模式有一个别称:快照。因此,你也许对它的作用就有了直觉上的认知。
在使用时,原型模式可以作为该模式的简化版本存在。
以下是它和原型模式之间的不同之处:
区别 | 备忘录模式 | 原型模式 |
---|---|---|
目的差异 | 专门为状态捕获和恢复而设计,核心是保存对象内部状态快照。 | 主要目的是通过克隆创建新对象,状态保存只是其副产品。 |
实现方式 | 显式管理状态 | 隐式复制整个对象 |
性能 | 只保存必要状态数据,内存占用更优。 | 完整对象克隆,资源消耗更大。 |
适用场景 | 需要精细控制状态保存/恢复的场合 | 创建对象成本高的场景 |
状态数据量大的场景 | 需要对象副本但不需要关心内部状态的场景 | |
需要保存状态历史记录的情况 | 需要保持对象创建独立性的情况 |
备忘录模式的核心组件包括三个组件:发起者、备忘录和管理者。
发起者是直接导致需要进行快照的对象状态变更的类。在 VFP 中,大致可以这样定义:
Define Class Originator As Custom
Protected oStatus = .Null.
Procedure Init(toObject As Object)
This.oStatus = m.toObject
Endproc
Procedure DoSomething()
*!* 针对 oStatus 所存储的对象的一些操作
Endproc
Procedure Save() As IMemento
Return Createobject("", This.oStatus)
Endproc
Procedure Restore(toMemento As IMemento)
*!* 从快照恢复
*!* This.oStatus = ......
Endproc
Enddefine
备忘录(快照)需要基于一个模板:
Define Class IMemento
*** <summary>
*** 获取快照信息的一些方法
*** </summary>
*** <remarks>可能是多个方法</remarks>
Procedure DoSomething()
Endproc
Enddefine
针对特定的业务逻辑,创建其特定的备忘录(快照)类:
Define Class ConcreteMemento As IMemento
Protected aDateTime[1]= {^}
Protected aStatus[1] = .Null.
Procedure Init(toObject As Object)
If This.aDateTime[1] = {^}
This.aDateTime[1] = Datetime()
This.aStatus[1] = m.toObject
Else
This.Add(m.toObject)
Endif
Endproc
Procedure DoSomething()
*!* 获取快照信息
*!* Return ......
EndProc
Procedure Add(toObject As Object)
Dimension This.aDateTime[Alen(This.aDateTime) + 1]
Dimension This.aStatus[Alen(This.aStatus) + 1]
This.aDateTime[Alen(This.aDateTime)] = Datetime()
This.aStatus[Alen(This.aStatus)] = m.toObject
EndProc
Enddefine
管理者的定义就比较简单:
Define Class CareTaker As Custom
Protected oMemento = .Null.
Protected oOriginator = .Null.
Procedure Init(toOriginator As Originator, toMemento As IMemento)
This.oOriginator = m.toOriginator
This.oMemento = m.toMemento
Endproc
Procedure BackUp()
This.oMemento.Add(This.oOriginator.Save())
Endproc
Procedure Undo()
*!* 依据条件从快照进行恢复
With This.oMemento
*!* 处理快照
Endwith
This.oOriginator.Restore(This.oMemento)
Endproc
Procedure ShowHistory()
*!* 显示对象各时间节点的快照
Endproc
Enddefine
剩余的就是在应用中的代码:
*!* 假设存在变量 m.loObject
Local loOriginator As Originator, loCareTaker As CareTaker
m.loOriginator = CreateObject("Originator", m.loObject)
m.loCareTaker = CreateObject("CareTaker", m.loOriginator, CreateObject("ConcreteMemento", m.loObject))
m.loCareTaker.BackUp()
*!* 对 m.loObject 进行一些操作 或者
m.loOriginator.DoSomething()
m.loCareTaker.BackUp()
m.loCareTaker.ShowHestory()
m.loCareTaker.Undo()
m.loCareTaker.ShowHestory()
以上基本上就是该设计模式在 VFP 中的基本实现。
我知道这很难理解,我也琢磨了好几天才基本明白。事实上,我在理解其他的设计模式时所花的时间更长......然后,我悲哀的发现,我之前所学的 VFP 有一半都是“假的”。
因此,从六月份开始,预计使用两三个月的时间(每周的周六、周日)对那些愿意学习设计模式的 VFP 开发者进行一次系统的培训,如果您恰巧看到此处,并且恰巧对此有兴趣,欢迎报名参与。
未完待续......