github地址:https://github.com/cheesezh/python_design_patternspython
用代碼模擬如下場景,一個遊戲角色有生命力,攻擊力,防護力等數據,在打Boss先後的數據值會發生變化,若是玩家挑戰Boss失敗,咱們容許玩家能夠將遊戲數據恢復到與Boss決鬥以前的狀態。git
class GameRole(): def __init__(self): self.vitality = 0 self.attack = 0 self.defense = 0 def state_display(self): print("當前角色狀態:") print("體力:",self.vitality) print("攻擊:",self.attack) print("防護:",self.defense) def get_init_state(self): """ 從服務器或者本地磁盤加載初始狀態 """ self.vitality = 100 self.attack = 100 self.defense = 100 def fight(self): """ 與Boss決鬥,數據損耗爲0 """ self.vitality = 0 self.attack = 0 self.defense = 0 def main(): mario = GameRole() mario.get_init_state() # 大戰Boss前,獲取初始角色狀態 mario.state_display() backup = GameRole() # 保存遊戲進度 backup.vitality = mario.vitality backup.attack = mario.attack backup.defense = mario.defense mario.fight() # 大戰Boss mario.state_display() mario.vitality = backup.vitality # 讀取進度,從新來過 mario.attack = backup.attack mario.defense = backup.defense mario.state_display() main()
當前角色狀態: 體力: 100 攻擊: 100 防護: 100 當前角色狀態: 體力: 0 攻擊: 0 防護: 0 當前角色狀態: 體力: 100 攻擊: 100 防護: 100
主要問題在於客戶端調用:github
備忘錄模式,在不破壞封裝性的前提下,捕獲一個對象的內部狀態,並在該對象以外保存這個狀態。這樣之後就可將該對象恢復到原先保存的狀態。主要包括三種類:服務器
在題目的場景中,遊戲角色類至關於Originator,使用一樣的「遊戲角色」實例「backup」來作備忘錄,這在當須要保存所有信息時,是能夠考慮的,而用clone的方式來實現Memento的狀態保存多是更好的方法,可是這樣就至關於對上層應用開放了Originator的所有接口,這對於保存備份有時候並不合適。code
那麼當咱們不須要保存所有信息以備使用時,須要怎麼辦?當咱們須要保存的並非所有信息,而只是部分信息,那麼就應該有獨立的備忘錄類Memento,它只擁有須要保存的信息的屬性。對象
class GameRole(): def __init__(self): self.vitality = 0 self.attack = 0 self.defense = 0 def state_display(self): print("當前角色狀態:") print("體力:",self.vitality) print("攻擊:",self.attack) print("防護:",self.defense) def get_init_state(self): """ 從服務器或者本地磁盤加載初始狀態 """ self.vitality = 100 self.attack = 100 self.defense = 100 def fight(self): """ 與Boss決鬥,數據損耗爲0 """ self.vitality = 0 self.attack = 0 self.defense = 0 def save_state(self): """ 新增「保存狀態」的方法 """ return RoleStateMemento(self.vitality, self.attack, self.defense) def recovery_state(self, memento): """ 新增「恢復狀態」的方法 """ self.vitality = memento.vitality self.attack = memento.attack self.defense = memento.defense class RoleStateMemento(): """ 遊戲角色狀態存儲箱 """ def __init__(self, vitality, attack, defense): self.vitality = vitality self.attack = attack self.defense = defense class RoleStateCaretaker(): """ 角色狀態管理者類 """ def __init__(self): self.memento = None def main(): mario = GameRole() mario.get_init_state() mario.state_display() state_admin = RoleStateCaretaker() state_admin.memento = mario.save_state() # 遊戲角色的保存對客戶端是透明的 mario.fight() mario.state_display() mario.recovery_state(state_admin.memento) # 遊戲角色的恢復對客戶端是透明的 mario.state_display() main()
當前角色狀態: 體力: 100 攻擊: 100 防護: 100 當前角色狀態: 體力: 0 攻擊: 0 防護: 0 當前角色狀態: 體力: 100 攻擊: 100 防護: 100
將須要保存的細節封裝在Memento類中,那一天要更改保存的細節也不用影響客戶端。接口
Memento模式比較適用於功能複雜的,但須要維護或記錄屬性歷史的類,或者須要保存的屬性只是衆多屬性中的一小部分時,Originator能夠根據保存的Memento信息還原到前一狀態。遊戲
命令模式也有相似的撤銷做用,若是在某個系統中使用命令模式時,須要實現命令的撤銷功能,那麼命令模式可使用備忘錄模式來存儲可撤銷操做的狀態。有時候一些對象的內部信息必須保存在對象之外的地方,可是必需要由對象本身讀取,這時,使用備忘錄能夠把複雜的對象內部信息對其餘的對象屏蔽起來,從而能夠恰當的保持封裝的邊界。get
當角色的狀態改變的時候,有可能這個狀態無效,這時候就可使用暫時存儲起來的備忘錄將狀態復原。it