1. 什么是備忘錄模式?
備忘錄模式是一種行為設計模式,它允許在不暴露對象內部狀態的情況下,保存和恢復對象的狀態。備忘錄模式的核心思想是將對象的狀態保存到一個備忘錄對象中,以便在需要時可以恢復到之前的狀態。這種模式通常用于實現撤銷操作或歷史記錄功能。
備忘錄模式通常包含三個主要組成部分:發起人(Originator)、備忘錄(Memento)和管理者(Caretaker)。
- 發起人(Originator):發起人是需要保存其狀態的對象。它負責創建一個備忘錄以保存其當前狀態,并可以使用備忘錄恢復其狀態。發起人通常包含一些業務邏輯和狀態信息。
- 備忘錄(Memento):備忘錄用于存儲發起人的內部狀態。備忘錄對象通常是不可變的,以防止外部對象修改其狀態。備忘錄只提供狀態的存儲,不提供任何業務邏輯。
- 管理者(Caretaker):管理者負責管理備忘錄對象,保存和恢復發起人的狀態。管理者不需要了解備忘錄的具體內容,只需保存和恢復。它通常維護一個備忘錄列表,以便在需要時可以訪問。
備忘錄模式在軟件設計中具有多種優點:
- 封裝性:備忘錄模式可以在不暴露對象內部狀態的情況下保存和恢復狀態。發起人可以將其狀態封裝在備忘錄對象中,外部對象無法直接訪問或修改這些狀態。
- 簡化代碼:通過將狀態管理邏輯分離到備忘錄對象中,可以簡化發起人的代碼。發起人只需關注其業務邏輯,而不必處理狀態的保存和恢復。
- 支持撤銷操作:備忘錄模式可以輕松實現撤銷操作,允許用戶恢復到之前的狀態。這在許多應用程序中都是一個重要的功能,例如文本編輯器、圖形編輯器等。
# 備忘錄類
class Memento:def __init__(self, state):self.__state = state # 將狀態設置為私有屬性def get_state(self):return self.__state # 提供訪問方法# 發起人類
class TextEditor:def __init__(self):self.text = ""def set_text(self, text):self.text = textprint(f"Current text: '{self.text}'")def save(self):return Memento(self.text)def restore(self, memento):self.text = memento.get_state()print(f"Restored text: '{self.text}'")# 管理者類
class Caretaker:def __init__(self):self.mementos = []def save_memento(self, memento):self.mementos.append(memento)def get_memento(self, index):return self.mementos[index]# 客戶端代碼
if __name__ == "__main__":def test1():editor = TextEditor()editor.set_text("Hello, World!")memento = editor.save() # 保存狀態# 嘗試直接訪問 memento.__statetry:print(memento.__state) # 這將引發 AttributeErrorexcept AttributeError:print("Cannot access memento state directly!") # 這行會被執行# 正確的方式是使用 get_state 方法print(f"Accessing memento state through method: '{memento.get_state()}'")def test2():editor = TextEditor()caretaker = Caretaker()editor.set_text("Hello, World!")caretaker.save_memento(editor.save()) # 保存狀態editor.set_text("Hello, Python!")caretaker.save_memento(editor.save()) # 保存新狀態# 恢復狀態editor.restore(caretaker.get_memento(0)) # 輸出: Restored text: 'Hello, World!'def test3():editor = TextEditor()caretaker = Caretaker()# 設置文本并保存狀態editor.set_text("Hello, World!")caretaker.save_memento(editor.save())editor.set_text("Hello, Python!")caretaker.save_memento(editor.save())# 撤銷到之前的狀態print("\nUndoing last operation:")last_memento = caretaker.get_memento(0) # 獲取第一個備忘錄editor.restore(last_memento) # 恢復到 'Hello, World!'# 繼續撤銷操作print("\nUndoing to initial state:")last_memento = caretaker.get_memento(1) # 獲取第二個備忘錄editor.restore(last_memento) # 恢復到 'Hello, Python!print('test1:')test1()print('\ntest2:')test2()print('\ntest3:')test3()
test1:
Current text: 'Hello, World!'
Cannot access memento state directly!
Accessing memento state through method: 'Hello, World!'test2:
Current text: 'Hello, World!'
Current text: 'Hello, Python!'
Restored text: 'Hello, World!'test3:
Current text: 'Hello, World!'
Current text: 'Hello, Python!'Undoing last operation:
Restored text: 'Hello, World!'Undoing to initial state:
Restored text: 'Hello, Python!'
代碼解析:
TextEditor
類是發起人,包含一個text
屬性來保存文本內容。set_text
方法用于設置文本并打印當前狀態。save
方法創建并返回一個備忘錄對象,保存當前文本狀態。restore
方法使用備忘錄對象恢復文本狀態
Memento
類用于存儲發起人的狀態。在這個例子中,它保存了文本編輯器的文本狀態。__state
屬性用于保存發起人的內部狀態,并通過get_state
方法提供訪問。
Caretaker
類負責管理備忘錄對象,維護一個mementos
列表來保存多個備忘錄。save_memento
方法用于將備忘錄對象添加到列表中。get_memento
方法根據索引返回相應的備忘錄對象。
- test1:
Memento
類封裝了TextEditor
的內部狀態。外部對象無法直接訪問Memento
的__state
屬性,從而保護了發起人的內部狀態。 - test2:
TextEditor
類的代碼保持簡潔,專注于文本的設置和恢復。狀態的管理邏輯被轉移到Caretaker
類中,從而簡化了發起人的代碼。 - test3: 用戶可以通過
Caretaker
類保存多個備忘錄,并在需要時恢復到之前的狀態。通過調用restore
方法,用戶可以輕松實現撤銷操作。