The memento design pattern is a behavioral design pattern which can be used when we have a requirement to restore the state of an object back to its previous state. The purpose of the memento design pattern is to provide the ability to execute an undo action in order to restore an object to a previous state.
The memento design pattern has three parts
1.Originator – the object that knows how to save itself.
2.Caretaker – the object that knows why and when the Originator needs to save and restore itself.
3. Memento – the lock box that is written and read by the Originator, and shepherded by the Caretaker.
Below is structure of the memento design pattern.
Lets say we need an undo like functionality build into our employee class salary property so that we can restore the employee object if required on some condition.
Lets code the originator hierarchy
public interface Originator { public Memento save(); public void restore(Memento memento); public void setSalary(float salary); }
public class EmployeeOriginator implements Originator { private String name; private int id; private String dob; private String city; private float salary; public EmployeeOriginator(String name, int id, String dob, String city, float salary) { super(); this.name = name; this.id = id; this.dob = dob; this.city = city; this.salary = salary; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getDob() { return dob; } public void setDob(String dob) { this.dob = dob; } public String getCity() { return city; } public void setCity(String city) { this.city = city; } public float getSalary() { return salary; } public void setSalary(float salary) { this.salary = salary; } @Override public Memento save() { // TODO Auto-generated method stub return new EmployeMemento(this.salary); } @Override public void restore(Memento memento) { this.salary = memento.getSalary(); } @Override public String toString() { return "EmployeeOriginator [name=" + name + ", id=" + id + ", dob=" + dob + ", city=" + city + ", salary=" + salary + "]"; } }
Lets code the memento hierarchy
public interface Memento { float getSalary(); }
public class EmployeMemento implements Memento { private float salary; public EmployeMemento(float salary) { super(); this.salary = salary; } public float getSalary() { return salary; } public void setSalary(float salary) { this.salary = salary; } }
Lets code the care taker hierarchy
public interface Caretaker { public Stack<Memento> stack = new Stack<Memento>(); public void addMemento(Memento m); public Memento getMemento(); }
public class EmployeCareTaker implements Caretaker { @Override public void addMemento(Memento m) { // TODO Auto-generated method stub stack.push(m); } @Override public Memento getMemento() { // TODO Auto-generated method stub return stack.pop(); } }
Lets put the code into test
public class Test { public static void main(String[] args) { Caretaker caretaker = new EmployeCareTaker(); Originator originator = new EmployeeOriginator("david",22,"1992-09-23","new york",80000); originator.setSalary(85000); System.out.println(originator); caretaker.addMemento(originator.save()); originator.setSalary(90000); caretaker.addMemento(originator.save()); originator.setSalary(95000); System.out.println(originator); originator.restore( caretaker.getMemento() ); System.out.println(originator); } }