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._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
- 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
TextEditor
que actúe como el Originator. - Crea una clase
TextMemento
que almacene el estado del texto. - 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
- 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