Intención del patrón
Sin violar el encapsulamiento, captura y externaliza el estado interno de un objeto para que el objeto pueda ser devuelto a dicho estado posteriormente.Una cookie mágica que encapsula un "punto de control".
Proporciona la capacidad de deshacer el estado completo de un objeto.
Ejemplo de problema
Se necesita restaurar un objeto a su estado previo (por ejemplo: operaciones del tipo "deshacer" o "rollback").Discusión
Un cliente solicita un Memento de un objeto cuando se necesita un punto de control del estado de dicho objeto. El objeto inicializa al Memento con una caracterización de su estado. El cliente es el "guardián" del Memento, pero sólo el objeto original puede almacenar y recuperar información del Memento (el Memento es "opaco" para el cliente y todos los demás objetos. Si el cliente más adelante necesita realizar un rollback sobre el estado del objeto origen, devuelve el Memento al objeto origen para que éste restaure su estado.Una capacidad ilimitada de "deshacer" y "rehacer" puede ser fácilmente implementada con una pila de objetos Command y una pila de objetos Memento.
El patrón de diseño Memento define tres roles diferentes:
- Originador: Es el objeto que sabe cómo resguardarse a sí mismo.
- Guardián: Es el objeto que conoce por qué y cuándo el Originador necesita almacenar y restaurarse a sí mismo.
- Memento: La "caja" de almacenamiento que es utilizado como almacenamiento por el Originador y cuidado por el Guardián.
Estructura
Ejemplo
El patrón de diseño Memento captura y exterioriza el estado interno de un objeto para que el mismo pueda ser restaurado a dicho estado. Este patrón es común entre los mecanismos de reparación "hágalo usted mismo" de frenos de tambor de autos. Los tambores son removidos de ambos lados, exponiendo ambos frenos, el derecho y el izquierdo. Sólo un lado es desarmado y el otro sirve como un Memento de cómo las partes del freno encajan juntas. Sólo después de haber finalizado el trabajo en un lado, se puede desarmar el otro. Cuando el segundo lado es desarmado, el primero actúa de Memento.Check list
- Identificar los roles de "guardián" y "Originador".
- Crear una clase Memento y declarar al Originador como friend.
- El guardián conoce cuando almacenar un "punto de control" del originador.
- El originador crea un Memento y copia su estado a dicho Memento.
- El guardián conserva al Memento pero sin conocer su contenido.
- El guardián sabe cuando debe volver al originador a su estado anterior.
- El originador se restablece a sí mismo utilizando el estado almacenado en el Memento.
Reglas de oro
Command y Memento actúan como tokens mágicos que son pasados e invocados posteriormente. En Command, el token representa una solicitud; en Memento representa el estado interno de un objeto en un momento determinado. El polimorfismo es importante para Command, pero no para Memento, porque su interfaz es tan reducida que sólo puede ser pasado como valor.Command puede usar a Memento para mantener un estado requerido para implementar una operación deshacer/rollback.
Memento es usado a menudo en conjunto con Iterator. Un objeto de tipo Iterator puede usar a un Memento para capturar el estado de una iteración. El Iterator almacena el Memento internamente.
Ejemplo de código en #
using System;
namespace DoFactory.GangOfFour.Memento.Structural
{
// MainApp startup class for Structural
// Memento Design Pattern.
class MainApp
{
// Entry point into console application.
static void Main()
{
Originator o = new Originator();
o.State = "On";
// Store internal state
Caretaker c = new Caretaker();
c.Memento = o.CreateMemento();
// Continue changing originator
o.State = "Off";
// Restore saved state
o.SetMemento(c.Memento);
// Wait for user
Console.ReadKey();
}
}
// The 'Originator' class
class Originator
{
private string _state;
// Property
public string State
{
get { return _state; }
set
{
_state = value;
Console.WriteLine("State = " + _state);
}
}
// Creates memento
public Memento CreateMemento()
{
return (new Memento(_state));
}
// Restores original state
public void SetMemento(Memento memento)
{
Console.WriteLine("Restoring state...");
State = memento.State;
}
}
// The 'Memento' class
class Memento
{
private string _state;
// Constructor
public Memento(string state) {
this._state = state;
}
// Gets or sets state
public string State
{
get { return _state; }
}
}
// The 'Caretaker' class
class Caretaker
{
private Memento _memento;
// Gets or sets memento
public Memento Memento
{
set { _memento = value; }
get { return _memento; }
}
}
}
2 comentarios:
Muy interesante, gracias
Me alegra que te haya parecido interesante.
Publicar un comentario
Muchas gracias por leer el post y comentarlo.