Introduction to Memento Design Pattern

In this article we are going to learn about Memento Pattern. What is memento pattern? How to implement?. What are the basic principle and where we can use it.
For code, I have used Java with eclipse and c# with VS2010.

What is Memento Pattern?
In OO design, some time we need to capture internal state of an object and restore that on certain condition or time, We can use memento pattern to resolve the situation.

Think like of doing UNDO operation. If we are in any calculation domain and our object do calculation, it is necessary to keep it undo able as well as keeping it neutral. We can use memento pattern easily with that. We will store every state if calculator object and we can undo them by giving back to previous state.
Or, think about Games. Let say, action game, when hero get health, the whole state need to be restore like as starting Or restring a level of game. Or even, in modern racing game, after garage work, the car need to be look same as beginning condition.

We can think of database and data table in a balance transfer operation. If the transfer is successful, the table state will be new, and if not, it will restored. A class will be responsible representing the table. The transaction manager object will keep record of table as memento object using originator and it will restore it.

Sometimes, the state can be store in file systems.

Basic Principle :
1. Capturing internal state of an object without violating encapsulation
2. Restoring that object's initial state.(or captured state). 

UML:


How to implement? 
So, lets think how to implement. Let's not look at the UML, try to make by our self. We need to capture an object state, means its all property values. So, it is called a subject(in UML it is mentioned as memento). It is stored in different states.
And, An way where it will be stored. Like, memento holders. Who will have an mechanism to store the state as well as return when ever it is necessary. (in UML, it is called Care Taker). We can also define an interface act as holder.
And, we need some one who will do the restoring process. (in UML it is called Originator) . It will creates a memento object to capture its own state and use the memento object to restore. Like as , set & get values from currently target memento and creates new memento and assign current value.

So, in summary. The originator store/restore state using memento object where care taker keeps the memento as record.

-Memento protects encapsulation and avoids exposing originator's internal state and implementation.
-Originator also need not to keep track as care taker does that.

Example : I have elasticated a very simple example. In here , I am going to store Current object state as State String. First, we will initiate the state (string) withe a string and then we will change it and after that we will restore it. I have used simple string, we can use our custom objects to do that.
So, lets plan. As I have stored the state as string so, that property should be present in both originator and memento object. That means, it will not know to main program but, will be known to originator and memento object. So, our memento class(I have kept the class as memento for better understanding)
public class Memento {
    private String state = "Not initiated";
    public Memento(String aState){
        state=aState;
        System.out.println("A memento is created");
    }
    public String getState(){
        System.out.println("State from Memento "+ state);
        return state;        
        }
}

And The originator who will have the main responsibilities.


public class Originator {
    private String state = "Originator state";
    public void set(String aState){
        state=aState;
        System.out.println("State from originator: "+state);
    }
    public Memento store(){
        System.out.println("memento created from originator");
        return new Memento(state);
    }
    public String restore(Memento aMemento){
        System.out.println("memento set from originator");
        state = aMemento.getState();
        return state;
    }
}

Now the container, that means care taker class


public class CareTaker {
    ArrayList<Memento> mementoes = new ArrayList<Memento>();
    public void add(Memento aMemento){
        mementoes.add(aMemento);
        System.out.println("One Item added, so no item count : "+mementoes.size());
    }
    public Memento getMemento(int index) {
        return mementoes.get(index);        
    }
}

Now the program class that contains main 


public class Program {
    public static void main(String[] args) {
        new Program();
    }
    CareTaker myStore = null;
    Originator originator = null;
    public static int itemNumber = 0;
    public Program(){
        myStore = new CareTaker();
        originator = new Originator();
        System.out.println("Storing Memento");
        originator.set("My Initial State");//Initial first time
        myStore.add(originator.store());
        itemNumber++;
        originator.set("My Changed State which will not be stored and will be restored");//Changed
        System.out.println("Restored : "+ originator.restore(myStore.getMemento(itemNumber-1)));//restored
    }
}

If we look at the code, we initiate and store the originator state using memento in care taker by this line
originator.set("My Initial State");
myStore.add(originator.store());


And we restore in the last section .
originator.restore(myStore.getMemento(itemNumber-1))

Java Example :
1. We can use interface/abstract class for common memento & originator. (I have not used)
2. We must keep the encapsulation carefully handled to keep integrity.
3. I have use console printing heavily so that we can understand the full code.
c# Example : 
1. I have changed method names as it is implemented differently
2. I have use small different type of implementations as dot net works little different than java.

Thanks...:)

No comments:

Post a Comment