Open In App

Memento Design Pattern | C++ Design Patterns

Memento Design Pattern is a behavioral design pattern that provides a mechanism for capturing an object’s internal state and restoring it to that state at a later time. This pattern is useful when we need to implement features like undo/redo functionality or when we want to save and restore an object’s state for various reasons.



Example for Memento Design Pattern in C++:

Problem Statement:

Suppose we have to represent two states by the use of memento patterns then we can use three classes to represent this Originator class to store the data then memento patterns for storing the state of originator then caretaker will hold the memento to solve the problem.



Key Component of Memento Method:

The Memento pattern aims to capture an object’s internal state, so it can be restored to that state later.

Step wise Implementation of above Example:

So In the above example, we have an Originator class that has an internal state, which can be saved and restored using the Memento pattern. The Caretaker class is responsible for managing the Memento objects, allowing you to save and restore the Originator’s state.

Originator: This is the object whose state we want to save and restore.




class Originator {
private:
    std::string state;
 
public:
    void SetState(const std::string& newState) {
        state = newState;
    }
 
    std::string GetState() const {
        return state;
    }
 
    Memento SaveStateToMemento() {
        return Memento(state);
    }
 
    void RestoreStateFromMemento(const Memento& memento) {
        state = memento.GetState();
    }
};

Memento: This class represents the saved state of the Originator.




class Memento {
private:
    std::string state;
 
public:
    Memento(const std::string& stateToSave) : state(stateToSave) {}
 
    std::string GetState() const {
        return state;
    }
};

Caretaker: The Caretaker is responsible for storing and managing the Mementos.




class Caretaker {
private:
    std::vector<Memento> mementos;
 
public:
    void AddMemento(const Memento& memento) {
        mementos.push_back(memento);
    }
 
    Memento GetMemento(int index) const {
        if (index >= 0 && index < mementos.size()) {
            return mementos[index];
        }
        throw std::out_of_range("Invalid memento index");
    }
};

Then in the main class we use all these stored classes to get the output.

Overall Code for above Example:




#include <iostream>
#include <string>
#include <vector>
 
// Originator: The object whose state needs to be saved and restored.
class Originator {
private:
    std::string state;
 
public:
    void SetState(const std::string& newState) {
        state = newState;
    }
 
    std::string GetState() const {
        return state;
    }
 
    // Memento: Inner class representing the state of the Originator.
    class Memento {
    private:
        std::string state;
 
    public:
        Memento(const std::string& originatorState) : state(originatorState) {}
 
        std::string GetSavedState() const {
            return state;
        }
    };
 
    // Create a Memento object to save the current state.
    Memento CreateMemento() const {
        return Memento(state);
    }
 
    // Restore the state from a Memento object.
    void RestoreState(const Memento& memento) {
        state = memento.GetSavedState();
    }
};
 
// Caretaker: Manages the Memento objects.
class Caretaker {
private:
    std::vector<Originator::Memento> mementos;
 
public:
    void AddMemento(const Originator::Memento& memento) {
        mementos.push_back(memento);
    }
 
    Originator::Memento GetMemento(int index) const {
        if (index >= 0 && index < mementos.size()) {
            return mementos[index];
        }
        throw std::out_of_range("Invalid Memento index");
    }
};
 
int main() {
    Originator originator;
    Caretaker caretaker;
 
    originator.SetState("State 1");
    caretaker.AddMemento(originator.CreateMemento());
 
    originator.SetState("State 2");
    caretaker.AddMemento(originator.CreateMemento());
 
    // Restore to the previous state
    originator.RestoreState(caretaker.GetMemento(0));
    std::cout << "Current state: " << originator.GetState() << std::endl;
 
    // Restore to an even earlier state
    originator.RestoreState(caretaker.GetMemento(1));
    std::cout << "Current state: " << originator.GetState() << std::endl;
 
    return 0;
}

Output
Current state: State 1
Current state: State 2






Diagrammatic Representation of Memento Method in C++:

Diagrammatic Representation of Momento Design Pattern in C++

In this example, we create an Originator object, change its state, and save the state into the Caretaker using the SaveStateToMemento method. Later, we can restore the state using the RestoreStateFromMemento method. The Caretaker is responsible for storing and managing the Mementos, allowing us to go back to previous states of the Originator.

Advantages of Memento Pattern in C++:

The Memento Pattern is a valuable tool for managing and preserving the state of objects in a way that enhances code modularity, flexibility, and maintainability, making it particularly useful in applications where state management is critical.

Disadvantages of Memento pattern in C++:


Article Tags :