memento-pattern
TL;DR⚑
- 메멘토는 스냅샷이라고도 불리며, 객체의 상태를 저장하는 역할을 수행함. 메멘토 객체는 직접 노출이 되지 않음에 유의
- 객체의 내부 상태를 캡슐화하여 외부에서 직접 접근할 수 없도록 하면서도, 이후 해당 상태를 복원할 수 있는 기능을 제공하는 패턴
- 사용자는 객체의 상태에 직접 접근할 필요 없이, Caretaker 객체가 노출하는 인터페이스를 통해 Originator 의 상태를 저장하고 복원할 수 있음
활용성⚑
- 객체의 상태를 저장하고 복원해야 할 때, 특히 객체의 상태가 복잡하여 여러 단계를 거쳐 변경되는 경우
- 객체의 정보를 저장하고, 특정 시점으로 돌아가야 하는 기능을 구현할 때 (예: 실행 취소 기능)
- 객체의 내부 상태가 외부에 노출되지 않도록 보호하면서도, 상태를 이전 상태로 복원할 수 있어야 할 때
결과⚑
-
장점
- 캡슐화 유지: 객체의 상태를 외부에 노출하지 않으면서도 상태 복원이 가능함.
- 실행 취소 기능 구현: 메멘토 패턴을 통해 상태를 저장하고 복원할 수 있으므로, 실행 취소 기능을 쉽게 구현할 수 있음.
- 복잡한 상태 관리: 객체의 복잡한 상태를 관리하고, 이전 상태로 돌아갈 수 있음.
-
단점
- 메모리 사용: 저장해야 하는 상태가 많거나 자주 변경될 경우, 메멘토 객체가 많이 생성되어 메모리 사용량이 증가할 수 있음.
- 관리 복잡성: 여러 시점의 상태를 관리해야 하므로, 메멘토 객체의 관리가 복잡해질 수 있음.
구현⚑
classDiagram
class Originator {
- state: str
+ do_something(): void
+ save(): Memento
+ restore(memento: Memento): void
}
class Memento {
- state: str
- date: str
+ get_state(): str
+ get_date(): str
}
class Caretaker {
- mementos: List~Memento~
- originator: Originator
+ backup(): void
+ undo(): void
+ show_history(): void
}
Originator --> Memento : creates
Caretaker --> Memento : stores
Caretaker --> Originator : interacts
Originator ..> Caretaker : uses
- Caretaker: 상태를 저장하고 복원할 수 있도록 메멘토 객체를 관리하는 역할.
- Originator: 상태를 생성하고, 필요한 시점에 상태를 복원할 수 있는 역할.
- Memento: Originator의 상태를 저장하는 역할로, 내부 상태를 캡슐화하여 외부에서 접근할 수 없도록 보호함.
예시 - Simple Case⚑
from datetime import datetime
# 메멘토 클래스
class Memento:
def __init__(self, state: str):
self._state = state
self._date = str(datetime.now())
def get_state(self) -> str:
return self._state
def get_date(self) -> str:
return self._date
# Originator 클래스
class Originator:
def __init__(self, state: str):
self._state = state
def do_something(self):
self._state = f"상태가 {self._state[::-1]}로 변경되었습니다."
def save(self) -> Memento:
return Memento(self._state)
def restore(self, memento: Memento):
self._state = memento.get_state()
# Caretaker 클래스
class Caretaker:
def __init__(self, originator: Originator):
self._mementos = []
self._originator = originator
def backup(self):
print(f"Caretaker: 상태 저장")
self._mementos.append(self._originator.save())
def undo(self):
if not self._mementos:
return
memento = self._mementos.pop()
print(f"Caretaker: 상태 복원 -> {memento.get_date()}")
self._originator.restore(memento)
def show_history(self):
print("Caretaker: 저장된 상태 목록:")
for memento in self._mementos:
print(memento.get_date(), "-", memento.get_state())
# 사용 예시
if __name__ == "__main__":
originator = Originator("초기 상태")
caretaker = Caretaker(originator)
caretaker.backup()
originator.do_something()
caretaker.backup()
originator.do_something()
caretaker.backup()
originator.do_something()
caretaker.show_history()
caretaker.undo()
caretaker.undo()
예시 - CareTaker 가 복수개라서, Originator 의 상태 동기화가 필요한 경우⚑
- 옵저버 패턴을 사용한다.
- Originator 가 Subject ( = Observable ) 이 되고, Caretaker 가 Observer 가 된다.
class Originator:
def __init__(self, state: str):
self._state = state
self._observers = []
def do_something(self):
self._state = f"상태가 {self._state[::-1]}로 변경되었습니다."
self._notify()
def save(self):
return self.Memento(self._state)
def restore(self, memento):
self._state = memento.get_state()
self._notify()
def attach(self, observer):
self._observers.append(observer)
def _notify(self):
for observer in self._observers:
observer.update(self)
def show_state(self):
print(f"현재 상태: {self._state}")
class Memento:
def __init__(self, state: str):
self._state = state
def get_state(self):
return self._state
class Caretaker:
def __init__(self, originator: Originator):
self._mementos = []
self._originator = originator
originator.attach(self)
def backup(self):
print("Caretaker: 상태를 저장합니다.")
self._mementos.append(self._originator.save())
def undo(self):
if not self._mementos:
return
memento = self._mementos.pop()
print("Caretaker: 상태를 복원합니다.")
self._originator.restore(memento)
def update(self, originator: Originator):
print("Caretaker: Originator의 상태가 변경되었습니다.")
self.backup()
if __name__ == "__main__":
originator = Originator("초기 상태")
caretaker1 = Caretaker(originator)
caretaker2 = Caretaker(originator)
originator.show_state()
originator.do_something()
caretaker1.undo()
originator.show_state()
caretaker2.undo()
originator.show_state()
요약⚑
메멘토 패턴은 객체의 상태를 저장하고 복원할 수 있는 기능을 제공하는 패턴입니다. 이 패턴을 사용하면, 객체의 내부 상태를 외부에 노출하지 않으면서도, 과거의 상태로 복원할 수 있습니다. 주로 실행 취소 기능이나 복잡한 상태 관리가 필요한 시스템에서 유용하게 사용됩니다.