What if we need to keep many different states of an object? We could keep the information inside objects with a lot of setters and make the code a big mess. This would indeed work but it would be awful to change anything in the future. As we developers know, software that does not change is dead.
When we need to manipulate different states of an object we can use the Memento Pattern.
Get the Design_Patterns_Saga_GitHub_Source_Code
1 – Memento: Nothing special here, it is just the object information we encapsulated in order to keep only part of the Customer information.
public class CustomerMemento { private String name; private String phone; public CustomerMemento(String name, String phone) { this.name = name; this.phone = phone; } // Getters and setters, hashcode and equals omitted. }
2 – Caretaker: it encapsulates the Memento object history in a Stack.
Methods:
save: it saves the state of the CustomerMemento object, pushing it to the top of the Stack.
revert: it reverts the state of the CustomerMemento to the last saved state.
public class Caretaker { private Stack<CustomerMemento> customerHistory = new Stack<>(); public void save(Customer customer) { customerHistory.push(customer.save()); } public void revert(Customer customer) { customer.revert(customerHistory.pop()); } }
3 – Originator: This is the main Customer object, the Originator of the information. There are two important methods here:
save: sets the name and phone from the Customer in the CustomerMemento object and returns the CustomerMemento.
revert: it reverts the Customer with the CustomerMemento information.
public class Customer implements Serializable { private static final long serialVersionUID = 574314732983681621L; private String name; private String address; private String phone; public Customer(String name, String address, String phone) { this.name = name; this.address = address; this.phone = phone; } public CustomerMemento save() { return new CustomerMemento(name, phone); } public void revert(CustomerMemento customer) { this.name = customer.getName(); this.phone = customer.getPhone(); } // Getters and setters, hashcode and equals omitted. }
Summary of actions:
- Created the Memento class with the necessary information.
- Created the Caretaker class.
- Declared the Stack to keep the Memento information into the Caretaker.
- Created the Originator class with all the Customer’s information.
- Created the save method that returns the CustomerMemento object.
- Created the revert method to put CustomerMemento information into Customer.
To practice the Memento Pattern you can create other Caretaker, Originator and Memento classes and make it work. Create another test method to make sure it works. Be sure to use TDD (Test Driven Development).