What is Memento Pattern in C#?
Tags: csharp
Published: 2024-02-09 07:12:41

The Memento Pattern is a behavioral design pattern that allows us to capture and restore an object's internal state without violating encapsulation. This pattern is useful when we want to provide an undo/redo functionality or to revert an object to its previous state.

In C#, we can implement the Memento Pattern using three main components: the Originator, the Memento, and the Caretaker.

The Originator is the object whose state we want to save. It should have methods to save and restore its state. Let's consider an example where we have a class called `TextEditor`:

```csharp
public class TextEditor
{
    private string _text;

    public string Text
    {
        get { return _text; }
        set { _text = value; }
    }

    public Memento CreateMemento()
    {
        return new Memento(_text);
    }

    public void RestoreMemento(Memento memento)
    {
        _text = memento.GetState();
    }
}
```

The `TextEditor` class has a `Text` property representing the current state of the text. It also has methods to create a memento and restore the state from a memento.

The Memento class is a container that stores the state of the Originator. It should have a method to retrieve the saved state. Let's create the `Memento` class:

```csharp
public class Memento
{
    private string _state;

    public Memento(string state)
    {
        _state = state;
    }

    public string GetState()
    {
        return _state;
    }
}
```

In this example, the `Memento` class has a constructor to initialize its state and a `GetState()` method to retrieve the saved state.

Finally, the Caretaker is responsible for storing and managing multiple mementos. It can stack the mementos or maintain a history of mementos for undo/redo functionality. Let's consider the `Caretaker` class:

```csharp
public class Caretaker
{
    private Stack<Memento> _mementos = new Stack<Memento>();

    public void SaveMemento(Memento memento)
    {
        _mementos.Push(memento);
    }

    public Memento GetLastMemento()
    {
        if (_mementos.Count > 0)
            return _mementos.Pop();

        return null;
    }
}
```

In this example, the `Caretaker` class uses a stack to store the mementos. We have methods to save a memento and retrieve the last saved memento.

Now, let's see how we can use these components together:

```csharp
class Program
{
    static void Main(string[] args)
    {
        TextEditor editor = new TextEditor();
        Caretaker caretaker = new Caretaker();

        editor.Text = "Hello, World!";
        caretaker.SaveMemento(editor.CreateMemento());

        editor.Text = "Hello, Design Patterns!";
        caretaker.SaveMemento(editor.CreateMemento());

        editor.Text = "Hello, C#!";

        editor.RestoreMemento(caretaker.GetLastMemento());
        Console.WriteLine(editor.Text);  // Output: Hello, Design Patterns!

        editor.RestoreMemento(caretaker.GetLastMemento());
        Console.WriteLine(editor.Text);  // Output: Hello, World!
    }
}
```

In this example, we create a `TextEditor` object and a `Caretaker` object. We set the editor's text, save the memento using the caretaker, change the text, and then restore the previous state from the memento using the caretaker.

The Memento Pattern allows us to easily save and restore an object's state without exposing its internal structure. It promotes the principle of encapsulation and enhances the reusability and flexibility of the code.