The Memento design pattern is a behavioral pattern that focuses on capturing and restoring an object’s internal state. It does so by providing a mechanism to store the state in a separate Memento object. The originator object creates and restores its state using these Memento objects, while ensuring that the state remains encapsulated and independent from other objects. The Memento pattern enhances the flexibility of object state management and supports undo operations.

Key Components of the Memento Pattern

  1. Originator: The Originator is the object whose state needs to be saved and restored. It creates and restores Memento objects that hold its internal state.
  2. Memento: The Memento represents the object’s state at a particular point in time. It stores the necessary data to restore the originator object’s state.
  3. Caretaker: The Caretaker is responsible for managing the Memento objects. It requests a Memento from the Originator, stores it, and can later provide it back to the Originator for state restoration.

Example:

Memento Pattern in Building Management: Let’s consider a scenario where we have a building management system that allows users to modify various properties of buildings, such as height, color, and number of floors. We can use the Memento pattern to capture and restore the building’s state.

class Building {
    private String name;
    private String color;
    private int height;
    private int numOfFloors;

    public Building(String name, String color, int height, int numOfFloors) {
        this.name = name;
        this.color = color;
        this.height = height;
        this.numOfFloors = numOfFloors;
    }

    public void setColor(String color) {
        this.color = color;
    }

    public void setHeight(int height) {
        this.height = height;
    }

    public void setNumOfFloors(int numOfFloors) {
        this.numOfFloors = numOfFloors;
    }

    public BuildingMemento saveState() {
        return new BuildingMemento(name, color, height, numOfFloors);
    }

    public void restoreState(BuildingMemento memento) {
        this.name = memento.getName();
        this.color = memento.getColor();
        this.height = memento.getHeight();
        this.numOfFloors = memento.getNumOfFloors();
    }

    @Override
    public String toString() {
        return "Building: " + name + ", Color: " + color + ", Height: " + height + ", Floors: " + numOfFloors;
    }
}

class BuildingMemento {
    private String name;
    private String color;
    private int height;
    private int numOfFloors;

    public BuildingMemento(String name, String color, int height, int numOfFloors) {
        this.name = name;
        this.color = color;
        this.height = height;
        this.numOfFloors = numOfFloors;
    }

    public String getName() {
        return name;
    }

    public String getColor() {
        return color;
    }

    public int getHeight() {
        return height;
    }

    public int getNumOfFloors() {
        return numOfFloors;
    }
}

In the above example, the Building class represents the originator object. It has various properties such as name, color, height, and number of floors, along with corresponding setter methods. The saveState() method creates a new BuildingMemento object, capturing the current state of the building. The restoreState() method restores the building’s state based on a provided BuildingMemento object.

The BuildingMemento class represents the memento object that stores the building’s state. It provides getters for each property to retrieve the state when needed.

By utilizing the Memento pattern, we can save and restore the state of buildings. This can be useful for undo functionality, tracking changes, or even checkpointing in a building management system.

Benefits and Use Cases of the Memento Design Pattern

The Memento design pattern offers several benefits:

  1. State Preservation: The Memento pattern allows capturing and storing the state of an object without violating encapsulation. It provides a convenient way to preserve object states.
  2. Undo/Redo Operations: By saving previous states and providing the ability to restore them, the Memento pattern supports undo and redo functionality. It enables reverting an object to a previous state, making it useful in applications where state history is crucial.
  3. Caretaker Independence: The Memento pattern ensures that the originator object’s state is encapsulated and independent from the caretaker. This promotes separation of concerns and maintains a clear division of responsibilities.
  4. Flexible State Management: The pattern allows for the management of multiple snapshots or checkpoints of an object’s state. It provides flexibility in choosing which states to restore.

The Memento pattern finds use in various scenarios, including:

  • Undo/Redo Functionality: The pattern is commonly used in applications where the ability to revert to previous states is essential, such as text editors, graphic design tools, or document management systems.
  • Checkpointing: In systems that require periodic snapshots or checkpoints of an object’s state, the Memento pattern can be employed to store these snapshots and restore them as needed.
  • Transactional Systems: The pattern can be utilized in transactional systems to roll back or revert changes when errors occur.

Conclusion

The Memento design pattern offers an elegant solution for preserving and restoring object states. By encapsulating and managing the state in separate memento objects, the pattern promotes loose coupling, supports undo functionality, and provides flexibility in state management.

In this blog post, we explored the Memento pattern and its practical application in the context of building management. Using the example of buildings and their states, we demonstrated how the Memento pattern enables the preservation and restoration of object states.

By leveraging the Memento pattern, software engineers and architects can design systems that effectively manage object state, support undo operations, and improve overall system flexibility. So, the next time you encounter a scenario that requires state preservation or undo functionality, consider applying the Memento pattern to achieve more robust and adaptable software.