Get up to 80 % extra points for free! More info:

Memento

Memento is a simple design pattern that stores the internal state of an object without violating the encapsulation principle. As the internal state is encapsulated within the object, the object must save the object data itself. The internal state can then be restored. The basic version of this pattern is not about the principle of history (undo and redo), but really just a single state that is saved and the object can be restored to it later. However, the principle of history can be implemented, even incrementally, to save only the changes against the original data. The pattern doesn't require any specific implementation of the state saving, we can use e.g. serialization for this purpose.

Motivation

In our applications, we may need an option to go back to the previous state in some places, for example, to get data from a form that the user has filled and the Internet connection has been lost when submitting it. We may also need to implement the undo/redo functions, these are handy whether you are programming a calculator or, for example, an editor. It might not surprise you that the pattern will separate this functionality into a separate object. This is, after all, the principle that most design patterns try to achieve. The original class keeping the state will remain clear from this logic and will be easier to maintain.

Pattern

The pattern includes the following classes:

  • Originator - The class whose state we are storing. Allows to restore its state from a memento or save it to a new memento and return it.
  • Memento - The representation of the internal state of the Originator class. Just an object keeping the state without any logic.
  • Caretaker - The class saves/restores mementos from/to the originator, it's is a state manager.
The Memento GOF design pattern – UML diagram - GOF - Behavioral Patterns

Example

Imagine we want to keep the history of calculator expressions. To keep things simple, let's save only whole expressions as strings. We'll use the stack data structure to represent the history. In practice, of course, you can save objects with multiple complex properties as well. We can program a generic Memento, so we can use it for other classes and won't need to write new classes over and over again.

The Memento class:

public class Memento<T>
{

    private T data;

    public Memento(T data) {
        this.data = data;
    }

    public T getData() {
        return data;
    }

}

The Originator (Calculator) class:

public class Calculator<T> {
    private T expression;

    public Memento<T> save() {
        return new Memento(expression);
    }

    public void load(Memento<T> memento) {
        expression = memento.getData();
    }

    public void setExpression(T expression) {
        this.expression = expression;
    }

    public T getExpression() {
        return expression;
    }

    // Other calculator methods...

}

And the Caretaker class:

public class Caretaker<T> {
    private Calculator<T> calculator;
    private Stack<Memento<T>> history = new Stack<Memento<T>>();

    public Caretaker(Calculator calculator) {
        this.calculator = calculator;
    }

    public void save() {
        history.push(calculator.save());
    }

    public void back() {
        calculator.load(history.pop());
    }

}

The use is as follows:

Calculator calculator = new Calculator();
Caretaker<String> history = new Caretaker<>(calculator);
calculator.setExpression("1 + 1");
System.out.println(calculator.getExpression());
history.save();
calculator.setExpression("2 * 3");
System.out.println(calculator.getExpression());
history.back();
System.out.println(calculator.getExpression());

And the application output:

Console application
1 + 1
2 * 3
1 + 1

If you are interested how to program the calculation of such a mathematical expression, the Interpreter design pattern solves it, it's also from GOF.


 

All articles in this section
GOF - Behavioral Patterns
Article has been written for you by David Capka Hartinger
Avatar
User rating:
No one has rated this quite yet, be the first one!
The author is a programmer, who likes web technologies and being the lead/chief article writer at ICT.social. He shares his knowledge with the community and is always looking to improve. He believes that anyone can do what they set their mind to.
Unicorn university David learned IT at the Unicorn University - a prestigious college providing education on IT and economics.
Activities