C++ Memento Pattern Example

1. Definition

The Memento Design Pattern provides a mechanism to capture an object's internal state such that it can be restored to this state at a later time. This pattern is particularly useful for implementing "undo" functionalities.

2. Problem Statement

In software systems, there might be a need to restore an object to its previous state, especially in applications like editors where undoing an operation is a common requirement. Directly exposing the internal state of an object may violate its encapsulation.

3. Solution

The Memento pattern involves three primary roles:

1. **Originator**: The object for which the state needs to be saved and restored.

2. **Memento**: The object that stores the state of the Originator.

3. **Caretaker**: The object that keeps track of the various states of the Originator.

4. Real-World Use Cases

1. Undo and redo functionality in word processors or graphic editors.

2. Saving game states in video games.

3. Taking snapshots of system configurations.

5. Implementation Steps

1. Define the Memento class that stores the internal state of the Originator.

2. Inside the Originator, implement a method to save its state to a memento and another method to restore its state from a memento.

3. The Caretaker manages the mementos but does not modify or look into the mementos.

6. Implementation in C++

// Step 1: Memento Class
class Memento {
    friend class Originator;
    int state;
    Memento(int s) : state(s) {}
public:
    ~Memento() {}
};
// Step 2: Originator Class
class Originator {
    int state;
public:
    Originator(int s) : state(s) {}
    Memento* createMemento() {
        return new Memento(state);
    }
    void setMemento(Memento* memento) {
        state = memento->state;
    }
    void showState() {
        std::cout << "Originator State: " << state << std::endl;
    }
    void doSomething() {
        std::cout << "Doing something...\n";
        state *= 2;  // example operation on state
    }
};
// Step 3: Caretaker Class
class Caretaker {
    Memento* memento;
public:
    void saveState(Originator* originator) {
        memento = originator->createMemento();
    }
    void restoreState(Originator* originator) {
        originator->setMemento(memento);
    }
};
// Example Usage
int main() {
    Originator originator(5);
    Caretaker caretaker;
    originator.showState();
    caretaker.saveState(&originator);
    originator.doSomething();
    originator.showState();
    caretaker.restoreState(&originator);
    originator.showState();
    return 0;
}

Output:

Originator State: 5
Doing something...
Originator State: 10
Originator State: 5

Explanation:

1. The Memento class stores the state of the Originator.

2. The Originator has methods to save its current state to a Memento and restore its state from a Memento.

3. The Caretaker manages the saved states but never looks into or modifies them.

In the example, we start with an originator state of 5. After "doing something" (doubling the state in this case), the state becomes 10. Using the memento saved by the caretaker, we restore the state back to 5.

7. When to use?

Use the Memento pattern when:

1. You need to implement an undo mechanism in an application.

2. The internal state of an object must be saved without violating its encapsulation.

3. The state-saving mechanism should not impact the object's primary responsibilities.


Comments