 |
Without violating encapsulation, capture and externalize an object's
internal state so that the object can be restored to this state later.
Frequency of use: low
|
|
 |
The classes and/or objects participating in this pattern are:
- Memento (Memento)
- stores internal state of the Originator
object. The memento may store as much or as little of the
originator's internal state as necessary at its originator's
discretion.
- protect against access by objects of other than the originator. Mementos
have effectively two interfaces. Caretaker sees a narrow interface to the
Memento -- it can only pass the memento to the other objects. Originator, in
contrast, sees a wide interface, one that lets it access all the data necessary to
restore itself to its previous state. Ideally, only the originator that produces
the memento would be permitted to access the memento's internal state.
- Originator (SalesProspect)
- creates a memento containing a snapshot
of its current internal state.
- uses the memento to restore its internal state
- Caretaker (Caretaker)
- is responsible for the memento's
safekeeping
- never operates on or examines the contents of a memento.
This structural code demonstrates the Memento pattern which temporary saves and
restores another object's internal state.
Show code
|
// Memento pattern -- Structural example
|
|
using System;
namespace DoFactory.GangOfFour.Memento.Structural
{
// MainApp test application
class MainApp
{
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.Read();
}
}
// "Originator"
class Originator
{
private string state;
// Property
public string State
{
get{ return state; }
set
{
state = value;
Console.WriteLine("State = " + state);
}
}
public Memento CreateMemento()
{
return (new Memento(state));
}
public void SetMemento(Memento memento)
{
Console.WriteLine("Restoring state:");
State = memento.State;
}
}
// "Memento"
class Memento
{
private string state;
// Constructor
public Memento(string state)
{
this.state = state;
}
// Property
public string State
{
get{ return state; }
}
}
// "Caretaker"
class Caretaker
{
private Memento memento;
// Property
public Memento Memento
{
set{ memento = value; }
get{ return memento; }
}
}
}
|
Output
State = On
State = Off
Restoring state:
State = On
|
This real-world code demonstrates the Memento pattern which temporarily saves and
then restores the SalesProspect's internal state.
Show code
|
// Memento pattern -- Real World example
|
|
using System;
namespace DoFactory.GangOfFour.Memento.RealWorld
{
// MainApp test application
class MainApp
{
static void Main()
{
SalesProspect s = new SalesProspect();
s.Name = "Noel van Halen";
s.Phone = "(412) 256-0990";
s.Budget = 25000.0;
// Store internal state
ProspectMemory m = new ProspectMemory();
m.Memento = s.SaveMemento();
// Continue changing originator
s.Name = "Leo Welch";
s.Phone = "(310) 209-7111";
s.Budget = 1000000.0;
// Restore saved state
s.RestoreMemento(m.Memento);
// Wait for user
Console.Read();
}
}
// "Originator"
class SalesProspect
{
private string name;
private string phone;
private double budget;
// Properties
public string Name
{
get{ return name; }
set
{
name = value;
Console.WriteLine("Name: " + name);
}
}
public string Phone
{
get{ return phone; }
set
{
phone = value;
Console.WriteLine("Phone: " + phone);
}
}
public double Budget
{
get{ return budget; }
set
{
budget = value;
Console.WriteLine("Budget: " + budget);
}
}
public Memento SaveMemento()
{
Console.WriteLine("\nSaving state --\n");
return new Memento(name, phone, budget);
}
public void RestoreMemento(Memento memento)
{
Console.WriteLine("\nRestoring state --\n");
this.Name = memento.Name;
this.Phone = memento.Phone;
this.Budget = memento.Budget;
}
}
// "Memento"
class Memento
{
private string name;
private string phone;
private double budget;
// Constructor
public Memento(string name, string phone, double budget)
{
this.name = name;
this.phone = phone;
this.budget = budget;
}
// Properties
public string Name
{
get{ return name; }
set{ name = value; }
}
public string Phone
{
get{ return phone; }
set{ phone = value; }
}
public double Budget
{
get{ return budget; }
set{ budget = value; }
}
}
// "Caretaker"
class ProspectMemory
{
private Memento memento;
// Property
public Memento Memento
{
set{ memento = value; }
get{ return memento; }
}
}
}
|
Output
Name: Noel van Halen
Phone: (412) 256-0990
Budget: 25000
Saving state --
Name: Leo Welch
Phone: (310) 209-7111
Budget: 1000000
Restoring state --
Name: Noel van Halen
Phone: (412) 256-0990
Budget: 25000
|
This .NET optimized code demonstrates the
same real-world situation as above but uses modern, built-in .NET features.
Show code
|
// Memento pattern -- .NET optimized
|
See our Singleton page for a .NET optimized code sample.
|
|
|