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:
- Originator: Crea un Memento que captura su estado actual y puede restaurar su estado a partir de un Memento.
- Memento: Almacena el estado interno del Originator.
- 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._statePaso 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._mementoPaso 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
- Originator: Tiene un estado interno que puede ser guardado en un Memento y restaurado desde un Memento.
- Memento: Almacena el estado del Originator.
- 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
- Crea una clase
TextEditorque actúe como el Originator. - Crea una clase
TextMementoque almacene el estado del texto. - Crea una clase
EditorHistoryque 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
- TextEditor: Actúa como el Originator, permitiendo escribir texto y crear/restaurar Mementos.
- TextMemento: Almacena el estado del texto.
- 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.
Curso de Patrones de Diseño de Software
Módulo 1: Introducción a los Patrones de Diseño
- ¿Qué son los Patrones de Diseño?
- Historia y Origen de los Patrones de Diseño
- Clasificación de los Patrones de Diseño
- Ventajas y Desventajas de Usar Patrones de Diseño
Módulo 2: Patrones Creacionales
- Introducción a los Patrones Creacionales
- Singleton
- Factory Method
- Abstract Factory
- Builder
- Prototype
Módulo 3: Patrones Estructurales
Módulo 4: Patrones de Comportamiento
- Introducción a los Patrones de Comportamiento
- Chain of Responsibility
- Command
- Interpreter
- Iterator
- Mediator
- Memento
- Observer
- State
- Strategy
- Template Method
- Visitor
Módulo 5: Aplicación de Patrones de Diseño
- Cómo Seleccionar el Patrón Adecuado
- Ejemplos Prácticos de Uso de Patrones
- Patrones de Diseño en Proyectos Reales
- Refactorización Usando Patrones de Diseño
Módulo 6: Patrones de Diseño Avanzados
- Patrones de Diseño en Arquitecturas Modernas
- Patrones de Diseño en Microservicios
- Patrones de Diseño en Sistemas Distribuidos
- Patrones de Diseño en Desarrollo Ágil
