(c) 2005 Marc Clifton All Rights Reserved.
There is no download associated with this article.
Introduction
The IMemento interface is simple yet powerful. Classes that implement
this interface can preserve and restore their state in any internal
representation that they choose. Classes that interface to classes
implementing IMemento can request that the instance save/restore its state
without knowing the details of the save/restore mechanism. While this can
deceive you into thinking that IMemento is a good way of managing persistent
information, it is not. For that, the usual n-tiered pattern, which
usually includes a data access layer, should be used. The IMemento is
useful in storing localized state information regarding an object. This
state information is disassociated with any other application information (as
in, it does not have any relationship to any other information in the
application).
Memento Design Pattern
The Memento design pattern is well known and you can read more about it
here.
The Eclipse project also has a good
write-up on it
here. One might not think that the Memento design pattern is worthy of
an entire article, but I feel that it is such a useful pattern that it can stand
on its own merits. Furthermore, this article describes extending the
Memento design pattern to something that I think is more useable for real world
applications. As the Memento design pattern stands, it is lacking some
features.
The typical design pattern looks like this:

The reality is though, that one rarely uses this a memento without also
associating some contextual information about the memento. Why was the
memento created? What did the user just do? What did the application
just do? For this reason, I find it more useful to have the Memento object
include an Action string:

If you read the documentation on the Memento design pattern, you'll notice
that there is an "Originator" class that implements SetMemento and CreateMemento
methods. For this mechanism to be truly useful, the class where you want
to preserve/restore state information should ideally tell the application that
it is capable of doing so, through it's own interface, which I have called "ISupportMemento":

Now we have all the players on the stage--classes that support mementos
always implement a standard interface mechanism, and the classes that the
implement the memento include some contextual information.
Interface Implementations
public interface IMemento
{
object State
{
get;
set;
}
string Action
{
get;
set;
}
}
public interface ISupportMemento
{
IMemento Memento
{
get;
set;
}
}
A Concrete Memento Class
If you don't have to deal with multiple inheritance issues, you can derive
your specialized memento class from a concrete Memento class rather than an
interface. Usually this should be the case, since the memento is managed
by a separate class rather than the originator class. The basic
implementation looks like this:
public class Memento : IMemento
{
protected object state;
protected string action;
public virtual object State
{
get {return state;}
set {state=value;}
}
public string Action
{
get {return action;}
set {action=value;}
}
}
You will note that I am using properties instead of discrete GetState/SetState
methods. Since the design patterns were originally written for C++, they
don't always look like what you'd probably want to implement in C#. So, my
actual IMemento interface looks like this, diagramatically:

Who Manages State?
Note that there's quite a bit of flexibility with regards to which object
creates the state information. I've illustrated two slightly different
implementations. In this example, the class implementing ISupportMemento
creates the state:
Example 1: Originator Creates The State Object
public class MyClass : ISupportMemento
{
public IMemento Memento
{
get
{
Memento mcm=new Memento();
mcm.State=GetMyState();
return mcm;
}
set
{
SetMyState(value.State);
}
protected object GetMyState()
{
// ... implementation ...
}
protected void SetMyState(object state)
{
// ... implementation ...
}
}
In this example, the class implementing the IMemento creates the state.
Example 2: Memento Creates The State Object
public class MyClass : ISupportMemento
{
public IMemento Memento
{
get
{
IMemento mcm=new MyClassMemento(this);
return mcm;
}
set
{
((MyClassMemento)value).SetState(this);
}
}
}
public class MyClassMemento : Memento
{
public MyClassMemento(MyClass mc)
{
// get MyClass state by querying properties of MyClass instance.
}
public void SetState(MyClass mc)
{
// set MyClass state by setting properties of MyClass instance.
}
}
The advantage with the second implementation is that you can change the
persistence mechanism without affecting the originator implementation--it is
independent of the originator class. However, the implementation is a bit
more complex and relies on casting the IMemento to the appropriate concrete
memento implementor, which can be prone to error if the wrong instance is passed
in.
Conclusion
I specifically wanted to avoid the topic of "how do you actually create the
state?" There are many answers--maybe the state is a simple value.
Maybe you want to use xml serialization, or binary serialization. In the
first example, the originator has the smarts to persist itself. In the
second example, you may want to decorate properties with an attribute that
provides information about what properties should be persisted. You may
want to include default values. So, as you can see, the issue of
persistence is itself complex.
One final note--you'll find the memento pattern used frequently in undo/redo
buffers, and this is why I've also included the Action contextual information in
my IMemento implementation.