第十四章 Caché 設計模式 備忘錄模式
定義
在不破壞封裝性的前提下,捕獲一個對象的內部狀態,並在該對象之外保存這個狀態。這樣以後就可將該對象回覆到原先保存的狀態。
使用場景
- 備忘錄模式比較適用於功能比較複雜的,但需要維護或記錄屬性歷史的類,或者需要保存的屬性只是衆多屬性中的一小部分時,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
{
q ##class(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
}
}
調用
/// d ##class(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>d ##class(PHA.YX.Design.Program).Memento()
當前角色狀態:
體力:100
攻擊力:100
防禦力:100
當前角色狀態:
體力:0
攻擊力:0
防禦力:0
當前角色狀態:
體力:100
攻擊力:100
防禦力:100
思考
記錄聽歌時的狀態(歌曲名稱,百分比,播放模式)。感興趣的同學實現後可以發我一起參考下。