定义

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

使用场景

备忘录模式比较适用于功能比较复杂的,但需要维护或记录属性历史的类,或者需要保存的属性只是众多属性中的一小部分时,Originator可以根据保存的Memento信息还原到前一状态。

如果在某个系统中使用命令模式时,需要实现命令的撤销功能,那么命令模式可以使用备忘录模式来储存可撤销操作的状态。

当角色的状态改变的时候,有可能在这个状态无效,这时候就可以使用暂时储存起来的备忘录将状态复原。

结构图

 

描述

玩游戏时,角色有体力值,攻击力,防御力。保存这些状态并恢复。

完整示例

角色类

Class PHA.YX.Design.Memento.GameRole Extends %RegisteredObject
{

Property vitality As %Integer [ Private ];

Method vitalityGet() As %Integer [ ServerOnly = 1 ]
{
	Quit i%vitality
}

Method vitalitySet(Arg As %Integer) As %Status [ ServerOnly = 1 ]
{
	s i%vitality = Arg
	Quit $$$OK
}

Property attact As %Integer [ Private ];

Method attactGet() As %Integer [ ServerOnly = 1 ]
{
	Quit i%attact
}

Method attactSet(Arg As %Integer) As %Status [ ServerOnly = 1 ]
{
	s i%attact = Arg
	Quit $$$OK
}

Property defense As %Integer [ Private ];

Method defenseGet() As %Integer [ ServerOnly = 1 ]
{
	
	Quit i%defense
}

Method defenseSet(Arg As %Integer) As %Status [ ServerOnly = 1 ]
{
	s i%defense = Arg
	Quit $$$OK
}

Method StateDisplay()
{
	w "当前角色状态:",!
	w "体力:" _ ..vitalityGet(),!
	w "攻击力:" _ ..attactGet(),!
	w "防御力:" _ ..defenseGet(),!
	w "",!
}

Method GetInitState()
{
	s ..vitality = 100
	s ..attact = 100
	s ..defense = 100
}

Method Fight()
{
	s ..vitality = 0
	s ..attact = 0
	s ..defense = 0
}

Method SaveState() As RoleStateMemento
{
	qclass(RoleStateMemento).%New(..vitality, ..attact, ..defense)
}

Method RecoveryState(memento As RoleStateMemento)
{
	s ..vitality = memento.vitalityGet()
	s ..attact = memento.attactGet()
	s ..defense = memento.defenseGet()
}

}

储存类

Class PHA.YX.Design.Memento.RoleStateMemento Extends %RegisteredObject
{

Property vitality As %Integer [ Private ];

Method vitalityGet() As %Integer [ ServerOnly = 1 ]
{
	Quit i%vitality
}

Method vitalitySet(Arg As %Integer) As %Status [ ServerOnly = 1 ]
{
	s i%vitality = Arg
	Quit $$$OK
}

Property attact As %Integer [ Private ];

Method attactGet() As %Integer [ ServerOnly = 1 ]
{
	Quit i%attact
}

Method attactSet(Arg As %Integer) As %Status [ ServerOnly = 1 ]
{
	s i%attact = Arg
	Quit $$$OK
}

Property defense As %Integer [ Private ];

Method defenseGet() As %Integer [ ServerOnly = 1 ]
{
	
	Quit i%defense
}

Method defenseSet(Arg As %Integer) As %Status [ ServerOnly = 1 ]
{
	s i%defense = Arg
	Quit $$$OK
}

Method %OnNew(vitality, attact, defense) As %Status [ Private, ServerOnly = 1 ]
{
	s ..vitality = vitality
	s ..attact = attact
	s ..defense = defense
	Quit $$$OK
}

}

管理类

Class PHA.YX.Design.Memento.RoleStateCaretaker Extends %RegisteredObject
{

Property memento As RoleStateMemento [ Private ];

Method mementoGet() As RoleStateMemento [ ServerOnly = 1 ]
{
	Quit i%memento
}

Method mementoSet(Arg As RoleStateMemento) As %Status [ ServerOnly = 1 ]
{
	s i%memento = Arg
	Quit $$$OK
}

}

调用

/// dclass(PHA.YX.Design.Program).Memento() 
ClassMethod Memento()
{
	/*进入游戏*/
	#dim yx as PHA.YX.Design.Memento.GameRole
	s yx =class(PHA.YX.Design.Memento.GameRole).%New()
	d yx.GetInitState()
	d yx.StateDisplay()
	
	/*保存进度*/
	#dim state as PHA.YX.Design.Memento.RoleStateCaretaker
	s state =class(PHA.YX.Design.Memento.RoleStateCaretaker).%New()
	d state.mementoSet(yx.SaveState())
	
	/*大战BOSS,损耗严重*/
	d yx.Fight()
	d yx.StateDisplay()
	
	/*恢复之前状态*/
	d yx.RecoveryState(state.mementoGet())
	d yx.StateDisplay()
}

DHC-APP>dclass(PHA.YX.Design.Program).Memento()
当前角色状态:
体力:100
攻击力:100
防御力:100
 
当前角色状态:
体力:0
攻击力:0
防御力:0
 
当前角色状态:
体力:100
攻击力:100
防御力:100

思考

记录听歌时的状态(歌曲名称,百分比,播放模式)。感兴趣的同学实现后可以发我一起参考下。