Назад к вопросам
Middle+
70
questionbank

Что такое паттерн 'Хранитель' (Memento)?

Sobes Copilot

Получайте ответы в реальном времени

Ответ от нейросети

sobes.tech AI

Паттерн проектирования "Хранитель" (Memento) позволяет сохранить и восстановить предшествующие состояния объекта без раскрытия деталей его реализации.

Основные роли:

  • Исходный объект (Originator): Объект, состояние которого нужно сохранить. Создает объект-хранитель и использует его для восстановления своего состояния.
  • Хранитель (Memento): Объект, который хранит состояние исходного объекта. Должен предоставлять минимально возможный интерфейс для доступа к хранимому состоянию, чтобы защитить его целостность.
  • Опекун (Caretaker): Отвечает за хранение хранителей. Запрашивает хранитель у исходного объекта и передает его обратно исходному объекту для восстановления. Опекун не взаимодействует напрямую с содержимым хранителя.

Принцип работы:

  1. Исходный объект создает хранитель, содержащий снимок своего текущего состояния.
  2. Опекун сохраняет этот хранитель (например, в списке).
  3. Когда нужно восстановить состояние исходного объекта, опекун передает сохраненный хранитель обратно исходному объекту.
  4. Исходный объект восстанавливает свое состояние из данных, хранящихся в хранителе.

Преимущества:

  • Сохранение инкапсуляции исходного объекта.
  • Позволяет реализовать механизмы отмены (undo) и возврата (redo).
  • Упрощает управление состояниями объекта.

Недостатки:

  • Создание хранителей может быть затратным по памяти, особенно для больших объектов.
  • Состояние хранителя может быть сложным для управления.

Пример реализации (упрощенный):

# Исходный объект
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" # Изменяем состояние
        print(f"Originator: 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 restored to {self._state}")

# Хранитель
class Memento:
    def __init__(self, state):
        self._state = state

    def get_state(self):
        return self._state

# Опекун
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() # Берем последний хранитель
        print(f"\nCaretaker: 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())