Introducción

El patrón de diseño Memento es un patrón de comportamiento que permite capturar y externalizar el estado interno de un objeto sin violar la encapsulación, de manera que el objeto pueda ser restaurado a este estado más tarde. Este patrón es útil cuando se necesita implementar funcionalidades de deshacer/rehacer en aplicaciones.

Conceptos Clave

  • Originator: El objeto cuyo estado se desea guardar.
  • Memento: El objeto que almacena el estado interno del Originator.
  • Caretaker: El objeto que solicita un Memento del Originator y lo guarda, pero no opera ni inspecciona su contenido.

Estructura del Patrón

El patrón Memento se compone de tres componentes principales:

  1. Originator: Crea un Memento que captura su estado actual y puede restaurar su estado a partir de un Memento.
  2. Memento: Almacena el estado interno del Originator.
  3. Caretaker: Guarda el Memento y lo utiliza para restaurar el estado del Originator.

Diagrama UML

+----------------+       +----------------+       +----------------+
|   Originator   |       |    Memento     |       |   Caretaker    |
+----------------+       +----------------+       +----------------+
| - state        |       | - state        |       | - memento      |
+----------------+       +----------------+       +----------------+
| + createMemento()      | + getState()   |       | + saveMemento()|
| + setMemento(memento)  | + setState()   |       | + getMemento() |
+----------------+       +----------------+       +----------------+

Ejemplo Práctico en Código

A continuación, se presenta un ejemplo en Python para ilustrar cómo implementar el patrón Memento.

Paso 1: Definir el 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 get_state(self):
        return self._state

    def set_state(self, state):
        self._state = state
        print(f"State set to: {self._state}")

Paso 2: Definir el Memento

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

    def get_state(self):
        return self._state

Paso 3: Definir el Caretaker

class Caretaker:
    def __init__(self):
        self._memento = None

    def save_memento(self, memento):
        self._memento = memento

    def get_memento(self):
        return self._memento

Paso 4: Uso del Patrón Memento

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

    # Save the state
    caretaker.save_memento(originator.create_memento())

    # Change the state
    originator.set_state("State2")

    # Restore the state
    originator.set_memento(caretaker.get_memento())
    print(f"Restored State: {originator.get_state()}")

Explicación del Código

  1. Originator: Tiene un estado interno que puede ser guardado en un Memento y restaurado desde un Memento.
  2. Memento: Almacena el estado del Originator.
  3. Caretaker: Guarda el Memento y lo utiliza para restaurar el estado del Originator.

Ejercicio Práctico

Ejercicio

Implementa un sistema de edición de texto simple que permita deshacer y rehacer cambios utilizando el patrón Memento.

Requisitos

  1. Crea una clase TextEditor que actúe como el Originator.
  2. Crea una clase TextMemento que almacene el estado del texto.
  3. Crea una clase EditorHistory que actúe como el Caretaker y permita guardar y restaurar estados.

Solución

class TextEditor:
    def __init__(self):
        self._text = ""

    def write(self, text):
        self._text += text

    def create_memento(self):
        return TextMemento(self._text)

    def set_memento(self, memento):
        self._text = memento.get_text()

    def get_text(self):
        return self._text

class TextMemento:
    def __init__(self, text):
        self._text = text

    def get_text(self):
        return self._text

class EditorHistory:
    def __init__(self):
        self._history = []

    def save_memento(self, memento):
        self._history.append(memento)

    def undo(self):
        if self._history:
            return self._history.pop()
        return None

if __name__ == "__main__":
    editor = TextEditor()
    history = EditorHistory()

    editor.write("Hello, ")
    history.save_memento(editor.create_memento())

    editor.write("world!")
    history.save_memento(editor.create_memento())

    print(f"Current Text: {editor.get_text()}")

    editor.set_memento(history.undo())
    print(f"After Undo: {editor.get_text()}")

    editor.set_memento(history.undo())
    print(f"After Second Undo: {editor.get_text()}")

Explicación de la Solución

  1. TextEditor: Actúa como el Originator, permitiendo escribir texto y crear/restaurar Mementos.
  2. TextMemento: Almacena el estado del texto.
  3. EditorHistory: Actúa como el Caretaker, permitiendo guardar y restaurar estados.

Conclusión

El patrón Memento es una herramienta poderosa para capturar y restaurar el estado de un objeto sin violar la encapsulación. Es especialmente útil en aplicaciones que requieren funcionalidades de deshacer/rehacer. A través de este módulo, hemos aprendido cómo implementar este patrón y cómo aplicarlo en un ejemplo práctico.

© Copyright 2024. Todos los derechos reservados