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
trait Originator { def save(): Memento; def restore(m: Memento); def salary_$eq(salary:Double); }
case class EmployeeOriginator(var name:String,id:Int,var dob:String,var city:String,var salary:Double) extends Originator { def save():Memento={ return new EmployeeMemento(this.salary); } def restore(m:Memento)={ this.salary=m.salary(); } }
Lets code the memento hierarchy
trait Memento { def salary():Double; }
class EmployeeMemento(var salary:Double) extends Memento { }
Lets code the care taker hierarchy
trait CareTaker { var stack=scala.collection.mutable.Stack[Memento](); def addMemento(m:Memento) def getMemento():Memento }
class EmployeeCareTaker extends CareTaker { def addMemento(m: Memento) = { stack.push(m) } def getMemento(): Memento = { stack.pop(); } }
Lets put the code into test
object Test extends App { val caretaker: CareTaker = new EmployeeCareTaker(); val originator: Originator = new EmployeeOriginator("david", 22, "1992-09-23", "new york", 80000); originator.salary_=(85000) System.out.println(originator); caretaker.addMemento(originator.save()) originator.salary_=(95000) caretaker.addMemento(originator.save()); originator.salary_=(98000) System.out.println(originator); originator.restore(caretaker.getMemento()); System.out.println(originator); }