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

Что такое паттерн 'Хранитель' (Memento) и в каких ситуациях его целесообразно использовать?

Sobes Copilot

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

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

sobes.tech AI

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

Применимость:

  • Когда необходимо сохранить состояние объекта для последующего восстановления.
  • Когда прямое сохранение состояния нарушило бы инкапсуляцию объекта.

Основные участники:

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

Пример:

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() # Если восстановление не удалось, пробуем предыдущий Memento

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

# Использование
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()