How to implement Memento pattern in Java?

Let’s say you are designing a shirt online using a tool.

You have created a design and saved it.

And suddenly you realize you want the old design back.

You find a menu to revert , you click it and you get back your old design.

Let’s get under the hoods and see how this revert could have worked.

Probably the tool used Memento pattern.

Memento pattern helps an object to retrieve its previous states.

Here is the client code :

package behavioural.memento.pattern;
public class Client {
	public static void main(String a[]) {
		ShirtDesign shirtDesign = new ShirtDesign();
		shirtDesign.setColor("blue");
		shirtDesign.setSize("Medium");
		shirtDesign.setStyle("Contemporary");
		System.out.println(shirtDesign);
		MementoOriginator originator = new MementoOriginator();
		ShirtDesignMemento memento = originator.createMemento(shirtDesign);
		MementoCareTaker careTaker = new MementoCareTaker();
		careTaker.pushMemento(memento);
		System.out.println("Changing design..");
		shirtDesign.setColor("yellow");
		shirtDesign.setSize("Large");
		System.out.println("New Design:" + shirtDesign);
		System.out.println("Retrieving back design");
		shirtDesign = originator.getShirtDesign(careTaker.popMemento());
		System.out.println("Original design: " + shirtDesign);
	}
}

As you see ,

I am creating a Shirt Design : blue colored , medium sized and of contemporary style.

And then I am storing this state of the object using a Memento.

Here are the steps to do that:

  • Create a Memento object – ShirtDesignMemento
  • Create a Originator class which will do the following:
    • It can create a memento object for a given ShirtDesign object
    • It can retrieve ShirtDesign object from a given memento object.
  • Create a CareTaker class which will do the following:
    • Add the memento objects to a stack to keep record of the history of shirt designs.
    • Pop the last memento object to retrieve the previous design.

The Originator creates a memento and gives it to the CareTaker .

The CareTaker takes care of the design by preserving it in a stack.

When the client wants the previous design , the CareTaker pops the latest design memento and gives it to the Originator.

The Originator converts the memento to the original design object and gives it to the client.

Here is the Originator class:

package behavioural.memento.pattern;
public class MementoOriginator {
	public ShirtDesignMemento createMemento(ShirtDesign shirtDesign) {
		ShirtDesignMemento memento = new ShirtDesignMemento();
		memento.setColor(shirtDesign.getColor());
		memento.setSize(shirtDesign.getSize());
		memento.setStyle(shirtDesign.getStyle());
		return memento;
	}
	public ShirtDesign getShirtDesign(ShirtDesignMemento memento) {
		ShirtDesign shirtDesign = new ShirtDesign();
		shirtDesign.setColor(memento.getColor());
		shirtDesign.setSize(memento.getSize());
		shirtDesign.setStyle(memento.getStyle());
		return shirtDesign;
	}
}

All it does is create memento for a given shirt design and create shirt design for a given memento.

Here is the CareTaker :

package behavioural.memento.pattern;
import java.util.Stack;
public class MementoCareTaker {
	private Stack<ShirtDesignMemento> mementoStack = new Stack<>();
	public void pushMemento(ShirtDesignMemento memento) {
		mementoStack.push(memento);
	}
	public ShirtDesignMemento popMemento() {
		return mementoStack.pop();
	}
}

All it does is maintain history of memento objects and pop the latest one when client requests it.

Here is the original ShirtDesign class:

package behavioural.memento.pattern;
public class ShirtDesign {
	private String color;
	private String size;
	private String style;
	public String getColor() {
		return color;
	}
	public void setColor(String color) {
		this.color = color;
	}
	public String getSize() {
		return size;
	}
	public void setSize(String size) {
		this.size = size;
	}
	public String getStyle() {
		return style;
	}
	public void setStyle(String style) {
		this.style = style;
	}
	@Override
	public String toString() {
		return "ShirtDesign [color=" + color + ", size=" + size + ", style=" + style + "]";
	}
}

Here is the memento class which has the same structure as the Shirt Design class:

package behavioural.memento.pattern;
public class ShirtDesignMemento {
	private String color;
	private String size;
	private String style;
	public String getColor() {
		return color;
	}
	public void setColor(String color) {
		this.color = color;
	}
	public String getSize() {
		return size;
	}
	public void setSize(String size) {
		this.size = size;
	}
	public String getStyle() {
		return style;
	}
	public void setStyle(String style) {
		this.style = style;
	}
}

Originator , CareTaker , Memento are the participants in this design pattern .

Let’s run the code .

Here is the output:

ShirtDesign [color=blue, size=Medium, style=Contemporary]
Changing design..
New Design:ShirtDesign [color=yellow, size=Large, style=Contemporary]
Retrieving back design
Original designShirtDesign [color=blue, size=Medium, style=Contemporary]

We reverted our design!

Quoting the Gang of Four:

Without violating encapsulation , capture and externalize an object’s internal state so that the object can be restored to this state later.

Here is the code:

https://github.com/vijaysrj/designPatternsGoF/tree/master/src/behavioural/memento/pattern


Posted

in

,

by

Comments

Leave a Reply

Discover more from The Full Stack Developer

Subscribe now to keep reading and get access to the full archive.

Continue reading