首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >设计模式:备忘录模式(Memento)

设计模式:备忘录模式(Memento)

作者头像
firstxinjie
发布2025-05-12 14:23:22
发布2025-05-12 14:23:22
8600
代码可运行
举报
文章被收录于专栏:X#(XSharp)X#(XSharp)
运行总次数:0
代码可运行

备忘录模式有一个别称:快照。因此,你也许对它的作用就有了直觉上的认知。

在使用时,原型模式可以作为该模式的简化版本存在。

以下是它和原型模式之间的不同之处:

区别

备忘录模式

原型模式

目的差异

专门为状态捕获和恢复而设计,核心是保存对象内部状态快照。

主要目的是通过克隆创建新对象,状态保存只是其副产品。

实现方式

显式管理状态

隐式复制整个对象

性能

只保存必要状态数据,内存占用更优。

完整对象克隆,资源消耗更大。

适用场景

需要精细控制状态保存/恢复的场合

创建对象成本高的场景

状态数据量大的场景

需要对象副本但不需要关心内部状态的场景

需要保存状态历史记录的情况

需要保持对象创建独立性的情况

备忘录模式的核心组件包括三个组件:发起者、备忘录和管理者。

发起者是直接导致需要进行快照的对象状态变更的类。在 VFP 中,大致可以这样定义:

代码语言:javascript
代码运行次数:0
运行
复制
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

备忘录(快照)需要基于一个模板:

代码语言:javascript
代码运行次数:0
运行
复制
Define Class IMemento
	*** <summary>
	*** 获取快照信息的一些方法
	*** </summary>
	*** <remarks>可能是多个方法</remarks>
      Procedure DoSomething()
      Endproc
Enddefine

针对特定的业务逻辑,创建其特定的备忘录(快照)类:

代码语言:javascript
代码运行次数:0
运行
复制
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

管理者的定义就比较简单:

代码语言:javascript
代码运行次数:0
运行
复制
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

剩余的就是在应用中的代码:

代码语言:javascript
代码运行次数:0
运行
复制
*!* 假设存在变量 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 开发者进行一次系统的培训,如果您恰巧看到此处,并且恰巧对此有兴趣,欢迎报名参与。

未完待续......

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2025-05-10,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 xinjie的VFP 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档