Memento Behavioral Patterns — Software Design Patterns

Kenny Ho
7 min readNov 12, 2020

Design patterns can be said to be the blueprint that tackles a particular software design issue. Just like how constructing a tall and sturdy building requires a blueprint that enables that structure; when encountered with a design problems in your code, respective design patterns acts like a blueprint that enables you to solve it.

There exists many issues faced when designing your software, corresponding to it, there exists many solutions and design patterns to it. The many design patterns differs in their complexity, level of detail and scale of applicability. However, through the individual pattern’s intent, they can be categorized into three main groups namely Creational, Structural and Behavioral.

Through this article, a particular Behavioral pattern will be discussed — Memento.

Memento

As mentioned, Memento is a behavioral pattern. Behavioral patterns in general take care of effective communication and the assignment of responsibilities between the objects in software; particularly, Memento allows one to save and restore previous state of an object without violation of encapsulation. This hides the implementation of details of the object from the other classes that are using it.

The ability to allow save and restore state is a very common feature that is widely used today — the undo function. Since this function is so widely used we shall use this as an example to demonstrate the use of Memento pattern.

The use of Memento Pattern

The problem:
Given a hypothetical scenario where you are developing a to-do list application and one of the main feature you wish to provide to the user is the ability to undo deleted to-do items. We implement a Todo class to store every instances of a to-do item. The class contains the metadata of a to-do item such as the date to do it by, note and description of to-do item as a field in the object. How are you going to implement the undo feature?

A direct approach will be having the application storing the state of the Todo object in the storage before the user perform any actions. Whenever the user triggers the undo button, your application fetches the latest snapshot from the storage and uses it to restore the state of the Todo object.

Before the command changes Todo, application save the snapshot of the object into a storage which can be retrieve later on.

To take a snapshot of the Todo object, you probably have to go through over all the fields in an object and copy their values into storage. This only can work if your class has public access rights for all its fields; usually not the case but let us assume it is for the sake of the discussion. However, even with this assumption idea of copying all fields into the storage, your application still face a very serious issue. It is now not open to future enhancements or refactoring which violates one of the Software Design Principles — Open-Closed Principle. This is due to the fact that if you wish to tag more data to your Todo class or remove from it, the class or classes that is responsible for duplicating the state will be affected.

Furthermore, your application will need to maintain some container that would store all the values of the individual Todo snapshot. It would then probably be stored in a list that would represent the histories of snapshots for undoing purposes. As you would need to allow other objects to write and read data directly to and from the container class, it will be forced to have close to no methods and filled with fields that mirror the Todo’s state. Thus, the other classes that interacts with the container would be tightly coupled with it. Every little change to the container class, would cause a ripple effect affecting the other classes.

The solution
To avoid the mess that we have mentioned above, we just have to adopt the Memento Pattern. The Memento pattern give the control of creating the snapshot state to the actual owner of that state, Todo class in the example above will be handling the duplication of its snapshot. Since it has full access to its own state, fields access rights can be private instead of public.

The pattern also suggests to store the copy of the Todo object’s state in a special object called memento. The contents of the memento will only be accessible to to the Todo object itself. Other objects/classes must and only will communicate with mementos through a limited interface. The interface only contain methods to access the snapshot’s metadata, but never the original object’s state. Below diagram shows an example of how you can implement undo feature with the help of Memento pattern.

This pattern allow you to store mementos inside other objects, usually called caretakers. The caretaker works with the memento only via the limited interface. The inability to tamper with the state stored inside the memento reduce coupling between them. At the same time, the originator Todo object has the access rights memento, allowing it to restore its previous state by setting its value to the ones in the memento.

In our Todo application example, we can create a separate history class to act as the caretaker. Using a stack data type, mementos can stored inside the caretaker which grows each time an operation is made. You possible could even render this stack within the app’s UI, displaying the history of previously performed operations to a user, extending your undo deletion feature to undoing changes all together.

Upon triggering undo, you can pop the stack to retrieve the most recent memento stored in the History object and passes it back to the Todo object replacing its state and achieve the undo feature.

In general, one can simply implement memento by following the diagram above and alter classes accordingly or follow this general diagram.

General diagram of how one can implement Memento pattern. Taken from: https://refactoring.guru/design-patterns/memento

Originator — The object that you wish to have state restoring and saving.
Memento — Acts as the snapshot of the originator usually have field mimicing that of the originator. Common practice is to make Memento immutable.
Caretaker —
One that keep tracks of the Originator’s history of states. Done through storing Memento typically in a stack. Should have knowledge of when to capture and restore the state.
Do take note that this general diagram implementation requires the ability to have nested class as Memento will be a nested class of the Originator. If the programming language does not support such nested class, you can simply extract out Memento class out to be an interface. The interface will then be implemented by a concrete class. Interaction is restricted by allowing Originator directly interact with the concrete class while caretakers interacts with the concrete class through the memento interface.

To sum up, below are the 9 steps to take while implementing Memento pattern.

  1. Determine what class that will be playing the originator role — usually ones that requires state restoration and saving.
  2. Create the memento class one by one and mimics its fields corresponding to that of the originator class.
  3. Make the memento class immutable. Only accept data once through the instantiation of Memento constructor. The class should have no setters.
  4. If nested classes are supported, nest the memento inside the originator. Otherwise convert memento class to an interface which will be implemented by a concrete class. Adding metadata operations to the interface is allowed, but never expose the originator’s state.
  5. Allow originator class to generate a memento through a method call.
  6. The return type of the method should be of the interface/nested class you in the previous step.
  7. Add state restoration method inside the Originator’s class which accepts a memento object as an argument. If an Memento interface is used in the previous step, make it the type of the parameter in the method. Typecasting will be needed to gain full access to that object for the Originator.
  8. The caretaker should have the knowledge of when to request new mementos from the originator, how to store it and when to restore which state with the corresponding memento.
  9. Interactions between caretakers and originators may be encapsulated in the memento class itself. If such decision was made, each memento instance must be connected to the originator that had created it. Restoration method would need to be move to the memento class.
    General note, only do this if the memento is a nested class or the originator provides relatively large amount of setters for memento class to override it.

The Benefits and Disadvantages of Memento Pattern

Advantages:

  • Encapsulation of code is maintained while producing snapshots of the object’s state.
  • Code is massively simplified by allowing caretaker classes to maintain the list of snapshot history of the originator class.

Disadvantages

  • If application creates mementos frequently, performance might be an issue due to high RAM usage.
  • The need for caretakers class to track the originator’s lifecycle destroying dead mementos.
  • Modern dynamic programming languages such as PHP, Python and JS does not guarantee access rights of Memento fields. Unwanted accessing of data might be allowed.

With all being said, Memento pattern do help reduces coupling and allow encapsulation of code whenever features like undo needs to be implemented in your software. However, as mentioned in the introduction, a blueprint only allows certain type of building to be constructed perfectly and is never a “one-size-fits-all” solution. Same idea applies to Design patterns. Memento pattern only solves design issues mentioned above and never all issues. Use it only if the problem fits such pattern, also keep in mind the restrictions it have to achieve its intended outcome. Hope this blog not only introduce you to Memento pattern but also give you an insight to when to and when not to use it.

References:
https://refactoring.guru/design-patterns/classification
https://refactoring.guru/design-patterns/memento

--

--