Aug 17, 2013

Memento Pattern

1 comment
Delegate some activity to some other class like some helper classes to do the job.

The memento pattern is used to encapsulate the current state of an object in a memento object in order to be able to restore the object state later without exposing the internal representation of the object to the outside world. The memento pattern is useful when you have an object which you would to take a "snapshot" of it. So that at a later time we could use the snapshot to restore it to its original state, such as an undo or rollback operation

UML Class Diagram
Example
Suppose we have an object which stores form information and we would like to allow the user to make changes in the form and then if they make a mistake later put back in the original form values.

Well, we could serialize the form object and then de-serialize it later but this is obviously messy and not a good solution. Another possible solution would be to have an outside object use the form's methods to pull out what you need to save the state but this causes high coupling between the class saving the state and the form; any changes in the form would require changes in the other class.

We need something that will allow us to save the state and restore it later without having to get involved in the details. This is where the memento pattern comes in.

 Implementation
Create memento class
/// 
/// Object that stores the previous state
/// 
/// 
public class Memento
{
    private T _state;

    public T State
{
        get { return _state; }
        set { _state = value; }
    }
}

Create a class(Originator) that we want to save and restore, such as a check point in an application
public class Originator
{
    private T state;

    // for saving the state
    public Memento CreateMemento()
    {
        Memento m = new Memento();
        m.State = state;
        return m;
    }

    // for restoring the state
    public void SetMemento(Memento m)
    {
        state = m.State;
    }

    // change the state of the Originator
    public void SetState(T state)
    {
        this.state = state;
    }

    // show the current state of the Originator
    public void ShowState()
    {
        Console.WriteLine(state.ToString());
    }
}

Create a class which stores objects that needs to be restored later,
public class Caretaker
{
    // List of states saved
    private static List> _mementoList = new List>();

    // Save state of the originator
    public static void SaveState(Originator orig)
    {
        _mementoList.Add(orig.CreateMemento());
    }

    // Restore originator state
    public static void RestoreState(Originator orig, int stateNumber)
    {
        orig.SetMemento(_mementoList[stateNumber]);
    }
}

Create a client to use above created memento pattern,
private void btnMemento_Click(object sender, EventArgs e)
{
    Originator orig = new Originator();

    orig.SetState("state0");
    Console.WriteLine("save state of the originator");
    Caretaker.SaveState(orig);
    orig.ShowState();

    orig.SetState("state1");
    Caretaker.SaveState(orig);
    orig.ShowState();
            
    Console.WriteLine("restore state of the originator to '0':");
    Caretaker.RestoreState(orig, 0);
    orig.ShowState();
}

Output
save state of the originator
 state0
state1
restore state of the originator to '0':
state0

1 comment :