Java design pattern: Memento

Today we will look at another Java design pattern from the category of behavioral patterns – Memento. Design patterns in this category deal with the communication (interaction) between objects and their responsibility.

What is the Memento design pattern?

The Memento design pattern allows the internal state of the object to be preserved without violating the encapsulation principle, which can be restored if necessary, thus returning the object to its original state.

What problem does the Memento design pattern solve?

In applications it is quite common to save the state that the user has entered as input to the program, e.g. when filling in the web form. In the event of a dropped internet connection, it is advisable to restore the last state of the entered data without asking the user again.

In similar situations where we need to store intermediate state and easily return to it at any time, the Memento design pattern is used, the principle of which is to decouple the storage of the object state from the object itself. The object that is to store its state creates a Memento object that contains the necessary state information. This Memento object can then be saved (e.g. to history) and later used to restore the object to its original state.

A well-designed object is encapsulated, that is, the object’s data is hidden inside and not accessible from outside the object, so the object itself – the Originator– is responsible for storing the internal state in the(Memento) object and restoring it from the(Memento) object. The client(Caretaker) takes the Memento object from the Originator object when the state is saved and passes it back to the Originator object when it is restored. This method makes it possible to save and restore the internal state of the Originator object without breaking its encapsulation.

Example of Memento implementation in Java

We demonstrate how to use the Memento design pattern to save and restore the state of an object without violating the encapsulation principle by playing a simple game where the player traverses progressively dangerous levels, where at each step he may suffer an injury, and where he can save the game state at any time and restore it as needed.

Game.java

package designpatterns;

public class Hra {
    private int levelId;
    private int zdravie;

    public Hra() {
        spustitHru();
    }

    public void spustitHru() {
        this.levelId = 1;
        this.zdravie = 100;
        System.out.println("Spúšťam novú hru.");
        ukazStavHry();
    }

    public Memento ulozitHru() {
        System.out.println("Ukladám stav hry.");
        return new Memento(levelId, zdravie);
    }

    public void nacitatHru(Memento memento) {
        System.out.println("Načítavam uloženú pozíciu v hre.");
        this.levelId = memento.getLevelId();
        this.zdravie = memento.getZdravie();
    }

    public void dokoncitLevel() {
        levelId++;
        System.out.println("Pokračujem do levelu " + levelId);
        ukazStavHry();
    }

    public void zranitSa(int poskodenie) {
        this.zdravie -= poskodenie;
        System.out.println("Hráč utrpel zranenie (" + -poskodenie + ")");
        ukazStavHry();
        if (zdravie <= 0) {
            System.out.println("Hráč stratil celé zdravie. Hra začne od začiatku.");
            spustitHru();
        }
    }

    public void ukazStavHry() {
        System.out.println("    Level " + levelId + ", Zdravie: " + zdravie);
    }
}

The Game class contains methods for starting a game, saving a game, loading a game, completing a level, injuring a player, and showing the game state.

Memento.java

package designpatterns;

public class Memento {
    private int levelId;
    private int zdravie;

    public Memento(int levelId, int zdravie) {
        this.levelId = levelId;
        this.zdravie = zdravie;
    }

    public int getLevelId() {
        return levelId;
    }

    public int getZdravie() {
        return zdravie;
    }
}

The Memento class serves as an object that stores the state of the game. Memento contains information about level(levelId) and health(health).

Hranie.java

import designpatterns.Hra;
import designpatterns.Memento;

public class Hranie {
    public static void main(String[] args) {
        Hra hra = new Hra();
        hra.zranitSa(12);
        hra.dokoncitLevel();
        Memento ulozenaPozicia = hra.ulozitHru();
        hra.zranitSa(24);
        hra.zranitSa(18);
        hra.dokoncitLevel();
        hra.zranitSa(20);
        hra.zranitSa(12);
        hra.zranitSa(14);
        hra.nacitatHru(ulozenaPozicia);
        hra.ukazStavHry();
    }
}

The Hranie class contains a main method that demonstrates the use of the Memento design pattern. The player starts the game, gets injured, completes the level, saves the game state (Memento), suffers another injury, completes another level, suffers another injury, and to avoid having to play the game from the beginning, finally resumes the game from the saved position.

The output of this example is:

Example output from the Memento design pattern.

Summary

The Memento pattern is a design pattern that solves the problem of storing and restoring the state of an object so that it is able to return to a previous state. It is often used to implement an undo/rollback mechanism or to keep a history of object states.

We have prepared the files with the above example in the form of code that you can run directly in Java. Download the Java Memento code here.

If you’re a Java developer looking for work, check out our employee benefits and respond to our job offers.

About the author

Jozef Wagner

Java Developer Senior

Viac ako 10 rokov programujem v Jave, momentálne pracujem v msg life Slovakia ako Java programátor senior a pomáham zákazníkom implementovať ich požiadavky do poistného softvéru Life Factory. Vo voľnom čase si rád oddýchnem v lese, prípadne si zahrám nejakú dobrú počítačovú hru.

Let us know about you