13 - Memento
Tags: flutter, dart, oop, programming
Published: 2021-04-13 15:04:31

In the last article, I have analysed a relatively popular design pattern — Command. In this article, I would like to analyse and implement a behavioural design pattern that works pretty well alongside the Command pattern — it is Memento.

## Table of Contents

* What is the Memento design pattern?
* Analysis
* Implementation
* Your Contribution

## What is the Memento design pattern?

![Making A Snapshot](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z14lgamkip5zfe53oxn6.gif)

**Memento**, also known as **Token**, belongs to the category of behavioural design patterns. The intention of this design pattern is described in the [GoF book](https://en.wikipedia.org/wiki/Design_Patterns):

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

The key idea in this pattern is to make an object (**originator**) itself responsible for saving and restoring its internal state. The internal state (a snapshot of it) is saved in another object — **memento**. The undo mechanism will request a memento from the originator when it needs to restore the originator’s internal state. Clients (**caretaker**) that are responsible for saving and restoring an originator’s internal state stores a list of memento objects so that a memento can be passed back to the originator to restore to a previous state. However, the caretaker itself isn’t permitted to access or modify a memento — only the originator object which created the specific memento is allowed to do that.

To understand the Memento design pattern better, let’s dive in by analysing its structure and implementation in more detail!

## Analysis

The general structure of the Memento design pattern looks like this:

![Memento Class Diagram](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/36bdnv54298yvm5h32h9.png)

* *Memento* — an interface which restricts access to the *ConcreteMemento’s* fields, only declares methods related to the memento’s metadata and which is used by the *Caretaker* to work with *ConcreteMemento* object;
* *ConcreteMemento* — stores an *Originator’s* internal state. Also, protects against access by objects other than the *Originator* which has created the *ConcreteMemento*.
* *Caretaker* — is responsible for the *Memento’s* safekeeping and never operates or examines the contents of a *Memento*.
* *Originator* — creates a *ConcreteMemento* containing a snapshot of its current internal state. Also, provides the *restore()* method to restore the internal state using the *ConcreteMemento*.

### Applicability

The Memento design pattern should be used when you want to produce snapshots of the object’s state to be able to restore a previous state of the object. The Memento pattern lets you make full copies of an object’s state, including private fields, and store them separately from the object.

Also, the pattern could be used for safety reasons — when direct access to the object’s fields/getters/setters violates its encapsulation. The Memento makes the object itself responsible for creating a snapshot of its state. No other object can read the snapshot, making the original object’s state data safe and secure.

## Implementation

![I'll Make It Work](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/myu1px85tm5sotr81rof.gif)

To implement the Memento design pattern and show its advantages, we will work further on the Command design pattern’s example. So if you have missed the previous article, I strongly recommend checking the implementation part of it now.

The main idea of the example remains the same — we will create a very simple, fake graphics editor. To simplify the Command design pattern’s part, only one command is created and available in the example’s UI — RandomisePropertiesCommand. This command randomises all the properties of the Shape object — height, width and colour — which acts as a state of our example.

Obviously, what is different from the previous implementation — the Memento design pattern is added. When implementing the Command design pattern’s example, we stored its state (Shape object) in the example component itself. This time, the state is stored inside the Originator object and could be manipulated only by it. The *RandomisePropertiesCommand* acts as a caretaker object and stores the previous snapshot of the originator’s state in the *backup* property. The *backup* property is nothing else than the *Memento* object which is created by the originator before executing the command.

As a result of using the Memento design pattern, the example’s state is encapsulated and moved outside from the example component. Also, the previous state could be restored from its Memento snapshot on *undo()* operation of the command. In this case, the Memento design pattern extends the Command design pattern and collaborates with it really well.

Before implementing the Memento design pattern and integrating it inside our example, let’s check the class diagram first and investigate its components.

### Class diagram

The class diagram below shows the implementation of the Memento design pattern:

![Memento Implementation Class Diagram](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pz9rse2zrg8x62x780ne.png)

*ICommand* is an abstract class that is used as an interface for the specific command:

* *execute()* — an abstract method that executes the command;
* *undo()* — an abstract method that undoes the command and returns the state to the previous snapshot of it.

*RandomisePropertiesCommand* is a concrete command which implements the abstract class *ICommand* and its methods.

*CommandHistory* is a simple class that stores a list of already executed commands (*commandList*) and provides methods to add a new command to the command history list (*add()*) and undo the last command from that list (*undo()*).

*IMemento* is an abstract class that is used as an interface for the specific memento class:

* *getState()* — an abstract method that returns the snapshot of the internal originator’s state.

*Memento* is a class that acts as a snapshot of the originator’s internal state which is stored in the *state* property and returned via the *getState()* method.

*Shape* is a simple data class that is used as an internal originator’s state. It stores multiple properties defining the shape presented in UI: *color*, *height* and *width*.

*Originator* — a simple class that contains its internal state and stores the snapshot of it to the *Memento* object using the *createMemento()* method. Also, the originator’s state could be restored from the provided *Memento* object using the *restore()* method.

*MementoExample* initializes and contains *CommandHistory*, *Originator* objects. Also, this component contains a *PlatformButton* widget that has the command of *RandomisePropertiesCommand* assigned to it. When the button is pressed, the command is executed and added to the command history list stored in *CommandHistory* object.

### Shape

A simple class to store information about the shape: its color, height and width. Also, this class contains several constructors:

* *Shape()* — a basic constructor to create a shape object with provided values;
* *Shape.initial()* — a named constructor to create a shape object with pre-defined initial values;
* *Shape.copy()* — a named constructor to create a shape object as a copy of the provided *Shape* value.

![shape.dart](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/g1h3jiq639hboovopaiy.png)

### ICommand

An interface that defines methods to be implemented by the specific command classes. Dart language does not support the interface as a class type, so we define an interface by creating an abstract class and providing a method header (name, return type, parameters) without the default implementation.

![icommand.dart](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/twruc9ca3zye683ka1k8.png)

### RandomisePropertiesCommand

A specific implementation of the command that sets all the properties of the *Shape* object stored in the *Originator* to random values. Also, the class implements the *undo* operation.

![randomise_properties_command.dart](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/39es085h1b84e8gvz34o.png)

### CommandHistory

A simple class that stores a list of already executed commands. Also, this class provides *isEmpty* getter method to return true if the command history list is empty. A new command could be added to the command history list via the *add()* method and the last command could be undone using the *undo()* method (if the command history list is not empty).

![command_history.dart](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/09iijyym1ykrbvxkt62y.png)

### IMemento

An interface that defines the *getState()* method to be implemented by the specific Memento class.

![imemento.dart](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cqvj011cm1j9lk6yv5c1.png)

### Memento

An implementation of the *IMemento* interface which stores the snapshot of *Originator’s* internal state (*Shape* object). The state is accessible to the *Originator* via the *getState()* method.

![memento.dart](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1a9ialrmqonu0nrzdaxt.png)

### Originator

A class that defines a *createMemento()* method to save the current internal state to a *Memento* object.

![originator.dart](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ew43rl1ul2po8tro02wc.png)

### Example

First of all, a markdown file is prepared and provided as a pattern’s description:

![Memento Markdown](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7ozr8jqmjjb6d8om695b.gif)

*MementoExample* contains *CommandHistory* and *Originator* objects. Also, this widget contains a *PlatformButton* component which uses the *RandomisePropertiesCommand* to randomise property values of the shape. After the command’s execution, it is added to the command history list stored in the *CommandHistory* object. If the command history is not empty, the *Undo* button is enabled and the last command could be undone.

![memento_example.dart](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ctb7ffqjbkh6vvdc7ekp.png)

As you can see in this example, the client code (UI elements, command history, etc.) isn’t coupled to any specific command class because it works with it via the *ICommand* interface.

In addition to what the Command design pattern provides to this example, the Memento design pattern adds an additional layer to the example’s state. It is stored inside the Originator object, the command itself does not mutate the state directly but through the Originator. Also, the backup (state’s snapshot) stored inside the Command is a Memento object and not the state (Shape object) itself — in case of the state’s restore (undo is triggered on the command), the specific command calls the restore method on the Originator which restores its internal state to the value stored in the snapshot. Hence, it allows restoring multiple property values (a whole complex state object) in a single request, while the state itself is completely separated from the command’s code or UI logic.

![Memento Example](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q65bi48d6wshnxunvxlo.gif)

As you can see in the example, when the command is executed, under the hood the snapshot of the originator’s internal state is stored which could be restored later by executing the undo operation on the command.

All of the code changes for the Memento design pattern and its example implementation could be found [here](https://github.com/mkobuolys/flutter-design-patterns/pull/14).

## Your Contribution

💖 or 🦄 this article to show your support and motivate me to write better!
💬 Leave a response to this article by providing your insights, comments or wishes for the next topic.
📢 Share this article with your friends, colleagues on social media.
➕ Follow me on dev.to or any other social media platform.
⭐ Star the [Github](https://github.com/mkobuolys/flutter-design-patterns) repository.