大話設計模式:第18章 備忘錄模式

第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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章