Memento - Design Pattern

Memento - Design Pattern

Software Architecture Simplified

Objective 🎯

Allow to save and restore a previous state of an object without violating encapsulation (not revealing details of its implementation).

Type

✔️Behavioral: Describes how objects interact/communicate between themselves.

Creational: Describes how to instantiate an object without large and complex.

Structural: Describes how objects/classes are composed to form larger structures.

UML 📐

image.png

Participants 🔗

• Memento:

  • Stores the internal state of the Originator object

• Originator:

  • Creates a memento object containing a snapshot of its current internal state
  • Uses memento to restore its internal state

• Caretaker:

  • Responsible for the memento’s safekeeping

Sample Code 🎮

Structural Example 🏛️

image.png

public static class MementoStructural
    {
        public static void Execute()
        {
            Originator lOriginator = new Originator();
            lOriginator.State = "On";

            // Store internal state
            Caretaker lCaretaker = new Caretaker();
            lCaretaker._Memento = lOriginator.CreateMemento();

            // Continue changing originator
            lOriginator.State = "Off";

            // Restore saved state
            lOriginator.SetMemento(lCaretaker._Memento);
        }
    }

    public class Originator
    {
        private string _State;

        public string State
        {
            get { return _State; }
            set
            {
                Console.WriteLine($"Originator - Changing state from \"{_State}\" to \"{value}\"");
                _State = value;
            }
        }

        public Memento CreateMemento()
        {
            Console.WriteLine($"Originator - Creating memento of the current state \"{_State}\"");
            return (new Memento(_State));
        }

        public void SetMemento(Memento prMemento)
        {
            Console.WriteLine($"Originator - Restoring state...");
            State = prMemento._State;
        }
    }

    public class Memento
    {
        public string _State { get; set; }

        public Memento(string prState)
        {
            _State = prState;
        }
    }

    public class Caretaker
    {
        public Memento _Memento { get; set; }
    }

Output

image.png

Real-world Example 🔥

image.png

public static class MementoPractical
    {
        public static void Execute()
        {
            WordDocument lWordDocument = new WordDocument();
            DocumentCaretaker lDocumentCaretaker = new DocumentCaretaker();

            lWordDocument.Content = "Content ABC";
            lWordDocument.SaveContentState(lDocumentCaretaker);

            lWordDocument.Content = "Content ABCDEFG";
            lWordDocument.RevertToLastSave(lDocumentCaretaker);

            lWordDocument.Content = "Content 123";
            lWordDocument.RevertToLastSave(lDocumentCaretaker);
        }
    }

    public class WordDocument
    {
        private string _Content;

        public string Content
        {
            get { return _Content; }
            set
            {
                Console.WriteLine($"WordDocument - Changing content from \"{_Content}\" to \"{value}\"");
                _Content = value;
            }
        }

        public void SaveContentState(DocumentCaretaker prDocumentCaretaker)
        {
            Console.WriteLine($"WordDocument - Saving current content");
            prDocumentCaretaker._DocumentMemento = new DocumentMemento(Content);
        }

        public void RevertToLastSave(DocumentCaretaker prDocumentCaretaker)
        {
            Console.WriteLine($"WordDocument - Restoring state...");
            Content = prDocumentCaretaker._DocumentMemento._Content;
        }
    }

    public class DocumentMemento
    {
        public string _Content { get; set; }

        public DocumentMemento(string _prContent)
        {
            _Content = _prContent;
        }
    }

    public class DocumentCaretaker
    {
        public DocumentMemento _DocumentMemento { get; set; }
    }

Output

image.png

Source Code 🎲

github.com/VictorLins/DesignPatterns

Did you find this article valuable?

Support Victor Lins by becoming a sponsor. Any amount is appreciated!