Sobes.tech
Middle+

What is the 'Caretaker' (Memento) pattern?

sobes.tech AI

Answer from AI

The "Memento" design pattern allows saving and restoring previous states of an object without revealing its implementation details.

Main roles:

  • Originator: The object whose state needs to be saved. Creates a memento object and uses it to restore its state.
  • Memento: The object that stores the state of the originator. It should provide a minimal interface to access the stored state to protect its integrity.
  • Caretaker: Responsible for storing mementos. It requests a memento from the originator and passes it back to restore the state. The caretaker does not interact directly with the contents of the memento.

Working principle:

  1. The originator creates a memento containing a snapshot of its current state.
  2. The caretaker saves this memento (e.g., in a list).
  3. When it is necessary to restore the originator's state, the caretaker passes the saved memento back to the originator.
  4. The originator restores its state from the data stored in the memento.

Advantages:

  • Preserves the encapsulation of the originator.
  • Enables undo and redo mechanisms.
  • Simplifies state management of the object.

Disadvantages:

  • Creating mementos can be memory-intensive, especially for large objects.
  • The state of the memento can be complex to manage.

Example implementation (simplified):

# Originator
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._state + "_changed" # Change state
        print(f"Originator: My state has changed to {self._state}")

    def save(self):
        print("Originator: Saving to Memento.")
        return Memento(self._state) # Create memento

    def restore(self, memento):
        self._state = memento.get_state() # Restore state from memento
        print(f"Originator: State restored to {self._state}")

# Memento
class Memento:
    def __init__(self, state):
        self._state = state

    def get_state(self):
        return self._state

# Caretaker
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:
            print("\nCaretaker: No mementos to restore.")
            return

        memento = self._mementos.pop() # Take the last memento
        print(f"\nCaretaker: Restoring state to: {memento.get_state()}")
        try:
            self._originator.restore(memento)
        except Exception:
            self.undo() # In case of error, try previous memento (optional)

    def show_history(self):
        print("Caretaker: Here's the list of mementos:")
        for memento in self._mementos:
            print(memento.get_state())