Introducció al Patró Memento

El patró Memento és un patró de disseny de comportament que permet capturar i externalitzar l'estat intern d'un objecte sense violar el seu encapsulament, de manera que l'objecte pugui ser restaurat a aquest estat més tard. Aquest patró és especialment útil quan es necessita implementar funcionalitats de desfer (undo) o historial.

Objectius del Patró Memento

  • Capturar l'estat intern d'un objecte: Permet guardar l'estat d'un objecte en un moment determinat.
  • Restaurar l'estat: Permet restaurar l'objecte a un estat anterior.
  • Encapsulament: Manté l'encapsulament de l'objecte, evitant que altres objectes accedeixin directament al seu estat intern.

Components del Patró Memento

El patró Memento consta de tres components principals:

  1. Originator: L'objecte que té un estat intern que necessita ser guardat i restaurat.
  2. Memento: Un objecte que emmagatzema l'estat intern de l'Originator.
  3. Caretaker: Un objecte que guarda el Memento i el retorna a l'Originator quan es necessita restaurar l'estat.

Diagrama de Classes

+----------------+       +-------------+       +-------------+
|   Originator   |<----->|   Memento   |<----->|  Caretaker  |
+----------------+       +-------------+       +-------------+
| - state        |       | - state     |       | - memento   |
| + createMemento()      | + getState()|       | + addMemento()|
| + setMemento()         | + setState()|       | + getMemento()|
+----------------+       +-------------+       +-------------+

Implementació en Codi

A continuació es presenta una implementació del patró Memento en Python:

Originator

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

    def create_memento(self):
        return Memento(self._state)

    def set_memento(self, memento):
        self._state = memento.get_state()

    def set_state(self, state):
        self._state = state

    def get_state(self):
        return self._state

    def __str__(self):
        return f"Originator(state={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):
        self._mementos = []

    def add_memento(self, memento):
        self._mementos.append(memento)

    def get_memento(self, index):
        return self._mementos[index]

Exemple d'Ús

if __name__ == "__main__":
    originator = Originator("State1")
    caretaker = Caretaker()

    # Guardar l'estat inicial
    caretaker.add_memento(originator.create_memento())

    # Canviar l'estat
    originator.set_state("State2")
    caretaker.add_memento(originator.create_memento())

    # Canviar l'estat novament
    originator.set_state("State3")

    print(f"Estat actual: {originator}")

    # Restaurar l'estat anterior
    originator.set_memento(caretaker.get_memento(1))
    print(f"Estat restaurat: {originator}")

    # Restaurar l'estat inicial
    originator.set_memento(caretaker.get_memento(0))
    print(f"Estat inicial restaurat: {originator}")

Exercicis Pràctics

Exercici 1: Implementar una Funcionalitat de Desfer

Implementa una funcionalitat de desfer (undo) utilitzant el patró Memento. Crea una classe TextEditor que permeti afegir text i desfer l'última operació.

Solució

class TextEditor:
    def __init__(self):
        self._content = ""
        self._caretaker = Caretaker()

    def write(self, text):
        self._caretaker.add_memento(Memento(self._content))
        self._content += text

    def undo(self):
        if self._caretaker._mementos:
            memento = self._caretaker.get_memento(len(self._caretaker._mementos) - 1)
            self._content = memento.get_state()
            self._caretaker._mementos.pop()

    def read(self):
        return self._content

if __name__ == "__main__":
    editor = TextEditor()
    editor.write("Hola, ")
    editor.write("món!")
    print(editor.read())  # Output: Hola, món!
    editor.undo()
    print(editor.read())  # Output: Hola, 
    editor.undo()
    print(editor.read())  # Output:

Resum

El patró Memento és una solució elegant per capturar i restaurar l'estat d'un objecte sense violar el seu encapsulament. És especialment útil en aplicacions que requereixen funcionalitats de desfer o historial. Amb una comprensió clara dels components i la implementació del patró, es poden crear sistemes més robustos i flexibles.

© Copyright 2024. Tots els drets reservats