第18章:備忘錄模式
備忘錄模式
備忘錄(memento)模式:在不破壞封裝性的前提下,捕獲一個對象的內部狀態,並在該對象之外保存這個狀態。這樣以後就可將該對象恢復到原先保存的狀態。
Originator
(發起人):負責創建一個備忘錄Memento
,用以記錄當前時刻其內部狀態,並可使用備忘錄恢復內部狀態。Originator
可根據需要決定Memento
存儲Originator
的哪些內部狀態。
Memento
(備忘錄):負責存儲Originator
對象的內部狀態,並可防止Originator
以外的其他對象訪間備忘錄Memento
。備忘錄有兩個接口,Caretaker
只能看到備忘錄的窄接口,它只能將備忘錄傳遞給其他對象。Originator
能夠看到一個寬接口,允許它訪問返回到先前狀態所需的所有數據。
Caretaker
(管理者):負責保存好備忘錄Memento
,不能對備忘錄的內容進行操作或檢查。
Originator
(發起人)類
Memento
(備忘錄)類
Caretaker
(管理者)類
客戶端代碼
備忘錄模式將要保存的細節封裝在Memento
中,更改保存的細節不會影響客戶端。
備忘錄模式的使用
-
備忘錄模式適用於功能比較複雜、但需要維護或記錄屬性歷史的類,或者需要保存的屬性只是衆多屬性中的一小部分時,
Originator
可以根據保存的Memento
信息還原到前一狀態。 -
如果在某個系統中使用命令模式時,需要實現命令的撤銷功能,那麼命令模式可以使用備忘錄模式來存儲可撤銷操作的狀態。
-
有時一些對象的內部信息必須保存在對象以外的地方,但是必須要由對象自己讀取,這時,使用備忘錄可以把複雜的對象內部信息對其他的對象屏蔽起來,從而可以恰當地保持封裝的邊界。
-
當角色的狀態改變的時候,有可能這個狀態無效,這時候就可以使用暫時存儲起來的備忘錄將狀態復原。
備忘錄模式示例
任務:遊戲進度保存
from typing import Text
class RoleStateMemento(object):
"""
角色狀態存儲箱類
"""
def __init__(self, vit: int, atk: int, def_: int) -> None:
self.__vit = vit
self.__atk = atk
self.__def = def_
@property
def vitality(self) -> int:
return self.__vit
@vitality.setter
def vitality(self, value: int) -> None:
self.__vit = value
@property
def attack(self) -> int:
return self.__atk
@attack.setter
def attack(self, value: int) -> None:
self.__atk = value
@property
def defense(self) -> int:
return self.__def
@defense.setter
def defense(self, value: int) -> None:
self.__def = value
class GameRole(object):
"""
遊戲角色類
"""
def __init__(self) -> None:
# 生命力
self.__vit = 0
# 攻擊力
self.__atk = 0
# 防禦力
self.__def = 0
@property
def vitality(self) -> int:
return self.__vit
@vitality.setter
def vitality(self, value: int) -> None:
self.__vit = value
@property
def attack(self) -> int:
return self.__atk
@attack.setter
def attack(self, value: int) -> None:
self.__atk = value
@property
def defense(self) -> int:
return self.__def
@defense.setter
def defense(self, value: int) -> None:
self.__def = value
def state_display(self) -> None:
"""
狀態顯示
"""
print("角色當前狀態:")
print("體力:{}".format(self.__vit))
print("攻擊力:{}".format(self.__atk))
print("防禦力:{}".format(self.__def))
def get_init_state(self) -> None:
"""
獲取初始狀態
"""
self.__vit = 100
self.__atk = 100
self.__def = 100
def fight(self) -> None:
"""
戰鬥
"""
self.__vit = 0
self.__atk = 0
self.__def = 0
def save_state(self) -> RoleStateMemento:
"""
保存角色狀態
"""
return RoleStateMemento(self.__vit, self.__atk, self.__def)
def recovery_state(self, memento: RoleStateMemento) -> None:
self.__vit = memento.vitality
self.__atk = memento.attack
self.__def = memento.defense
class RoleStateCaretaker(object):
"""
角色狀態管理者類
"""
def __init__(self) -> None:
self.__memento = None
@property
def memento(self) -> RoleStateMemento:
return self.__memento
@memento.setter
def memento(self, value: RoleStateMemento) -> None:
self.__memento = value
# 客戶端代碼
if __name__ == "__main__":
# 大戰Boss前
role = GameRole()
role.get_init_state()
role.state_display()
# 保存進度
state_admin = RoleStateCaretaker()
state_admin.memento = role.save_state()
# 大戰Boss時,損耗嚴重
role.fight()
role.state_display()
# 恢復之前狀態
role.recovery_state(state_admin.memento)
role.state_display()
角色當前狀態:
體力:100
攻擊力:100
防禦力:100
角色當前狀態:
體力:0
攻擊力:0
防禦力:0
角色當前狀態:
體力:100
攻擊力:100
防禦力:100