Middle+
What is the 'Keeper' (Memento) pattern and in what situations is it advisable to use?
sobes.tech AI
Answer from AI
The "Memento" pattern allows saving and restoring the previous state of an object without violating encapsulation.
Applicability:
- When it is necessary to save the state of an object for later restoration.
- When direct state saving would violate the object's encapsulation.
Main participants:
- Originator: The object whose state needs to be saved. Creates a snapshot (Memento) of its current state and can restore from it.
- Memento: The object that stores the state of the Originator. Provides an interface for accessing the state, limited to those who should know it.
- Caretaker: Stores the mementos. Does not know about the internal workings of the Originator and does not work with mementos directly, only passes them.
Example:
class Memento:
def __init__(self, state):
self._state = state
def get_state(self):
return self._state
class Originator:
def __init__(self, state):
self._state = state
print(f"Originator: Initial state is: {self._state}")
def do_something(self):
print("Originator: I'm doing something important.")
self._state = self._generate_random_string()
print(f"Originator: And my state has changed to: {self._state}")
def save(self):
print("Originator: Saving to Memento.")
return Memento(self._state)
def restore(self, memento):
self._state = memento.get_state()
print(f"Originator: State after restoring from Memento: {self._state}")
def _generate_random_string(self):
import random
import string
return ''.join(random.choices(string.ascii_uppercase + string.digits, k=10))
class Caretaker:
def __init__(self, originator):
self._originator = originator
self._mementos = []
def backup(self):
print("\nCaretaker: Saving Originator's state...")
self._mementos.append(self._originator.save())
def undo(self):
if not self._mementos:
return
memento = self._mementos.pop()
print(f"Caretaker: Restoring state to: {memento.get_state()}")
try:
self._originator.restore(memento)
except Exception:
self.undo()
def show_history(self):
print("Caretaker: Here's the list of mementos:")
for memento in self._mementos:
print(memento.get_state())
# Usage
originator = Originator("SuperState")
caretaker = Caretaker(originator)
caretaker.backup()
originator.do_something()
caretaker.backup()
originator.do_something()
caretaker.backup()
originator.do_something()
print("\n")
caretaker.show_history()
print("\nClient: Now, let's undo!")
caretaker.undo()
print("\nClient: Once more!")
caretaker.undo()