[Python設計模式] 第18章 遊戲角色備份——備忘錄模式

來源:互聯網
上載者:User

標籤:記錄   磁碟   開放   地址   不用   pat   design   目的   功能   

github地址:https://github.com/cheesezh/python_design_patterns

題目

用代碼類比以下情境,一個遊戲角色有生命力,攻擊力,防禦力等資料,在打Boss前後的資料值會發生變化,如果玩家挑戰Boss失敗,我們允許玩家可以將遊戲資料恢複到與Boss決鬥之前的狀態。

基礎版本
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
點評

主要問題在於用戶端調用:

  1. 遊戲角色細節暴露給了用戶端,用戶端需要知道遊戲角色的生命力,攻擊力,防禦力等細節;
  2. 用戶端還要對遊戲角色進行備份;
  3. 如果以後增加“魔法值”或者修改現有資料,都要更改用戶端;
  4. 恢複角色的過程也存在同樣問題;
備忘錄模式

備忘錄模式,在不破壞封裝性的前提下,捕獲一個對象的內部狀態,並在該對象之外儲存這個狀態。這樣以後就可將該對象恢複到原先儲存的狀態。主要包括三種類:

  • 發起人(Originator):負責建立一個備忘錄Memento,用以記錄當前時刻它的內部狀態,並可使用備忘錄恢複內部狀態。Originator可以根據需要決定Memento儲存Originator的哪些內部狀態;
  • 備忘錄(Memento):負責儲存Originator對象的內部狀態,並可防止Originator以外的其他對象訪問備忘錄Memento。備忘錄有兩個介面,Caretaker只能看到備忘錄的窄介面,它只能將備忘錄傳遞給其他對象。Originator可以看到一個寬介面,允許它訪問返回到先前狀態的所有資料;
  • 管理者(Caretaker):負責儲存好備忘錄Memento,不能對備忘錄的內容進行操作或檢查。

在題目的情境中,遊戲角色類相當於Originator,使用同樣的“遊戲角色”執行個體“backup”來做備忘錄,這在當需要儲存全部資訊時,是可以考慮的,而用clone的方式來實現Memento的狀態儲存可能是更好的方法,但是這樣就相當於對上層應用開放了Originator的全部介面,這對於儲存備份有時候並不合適。

那麼當我們不需要儲存全部資訊以備使用時,需要怎麼辦?當我們需要儲存的並不是全部資訊,而只是部分資訊,那麼就應該有獨立的備忘錄類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資訊還原到前一狀態。

命令模式也有類似的撤銷作用,如果在某個系統中使用命令模式時,需要實現命令的撤銷功能,那麼命令模式可以使用備忘錄模式來儲存可撤銷操作的狀態。有時候一些對象的內部資訊必須儲存在對象以外的地方,但是必須要由對象自己讀取,這時,使用備忘錄可以把複雜的對象內部資訊對其他的對象屏蔽起來,從而可以恰當的保持封裝的邊界。

當角色的狀態改變的時候,有可能這個狀態無效,這時候就可以使用暫時儲存起來的備忘錄將狀態複原。

[Python設計模式] 第18章 遊戲角色備份——備忘錄模式

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.