Memento Design Pattern

This one is pretty simple, so the post is going to be short. Basically, Memento Pattern is used to restore state of an object to a previous one. How is it used? Well, the following posts show that, too:
1. https://www.tutorialspoint.com/design_pattern/memento_pattern.htm
2. https://sourcemaking.com/design_patterns/memento

However, there are some problems with this approach. First of all, examples are not real-world (as always). Secondly, Memento should be revisited from structural point of view. I understand the intent to follow GoG tradition, but maybe the tradition should change a bit? In other words, it is fine to use patterns, but they should be clarified as much as possible. For instance, why there is a name such as CareTaker? It sounds not professional enough. I would suggest to call this like that: MementoList, MementoRepository, etc. In other words, use such names that actually make sense.

So, let us implement Memento in abstract way now. As we can see below, we have three actors – Originator, Memento itself, and MementoRepository (a.k.a. CareTaker for whatever it is).

class Memento<T>
{
    private T _state;
 
    public Memento(T state)
    {
        _state = state;
    }
 
    public T GetState()
    {
        return _state;
    }
}
 
class Originator<T>
{
    private T _state;
 
    public void SetCurrentState(T state)
    {
        _state = state;
    }
 
    public T GetCurrentState()
    {
        return _state;
    }
 
    public Memento<T> GetMemento()
    {
        return new Memento(_state);
    }
 
    public void SetStateFromMemento(Memento<T> memento)
    {
        _state = memento.GetState();
    }
}
 
class MementoRepository<T>
{
    private IList<Memento<T>> _mementos;
 
    public void Add(Memento<T> item)
    {
        _mementos.add(item);
    }
 
    public Memento<T> Get(int index) {
        return _mementos[index];
    }
}

Code sample could be the following:

Originator<String> originator = new Originator<>();
MementoRepository<String> repository = new MementoRepository<>();
 
originator.SetCurrentState("State #1");
originator.SetCurrentState("State #2");
repository.Add(originator.GetMemento());
 
originator.SetCurrentState("State #3");
repository.Add(originator.GetMemento());
 
originator.SetCurrentState("State #4");
originator.SetStateFromMemento(repository.Get(0));

And that is it. Memento Design pattern has been successfully implemented in an abstract way. Now let us take a closer look. In order to have less code, sometimes we can achieve the same functionality through usage of less code. For instance, what if we would use just two actors, i.e. Memento would be skipped? Would it still be a pattern? Actually, it would. See the code that proves this point below:

class Originator<T>
{
    private T _state;
 
    public void SetCurrentState(T state)
    {
        _state = state;
    }
 
    public T GetCurrentState()
    {
        return _state;
    }
}
 
class MementoRepository<T>
{
    private IList<Memento<T>> _mementos;
 
    public void Add(Memento<T> item)
    {
        _mementos.add(item);
    }
 
    public Memento<T> Get(int index)
    {
        return _mementos[index];
    }
}

Now the code sample above would become like this:

Originator<String> originator = new Originator<>();
MementoRepository<String> repository = new MementoRepository<>();
 
originator.SetCurrentState("State #1");
originator.SetCurrentState("State #2");
repository.Add(originator.GetCurrentState());
 
originator.SetCurrentState("State #3");
repository.Add(originator.GetCurrentState());
 
originator.SetCurrentState("State #4");
originator.SetCurrentState(repository.Get(0));

In other words, Memento object itself is not required at all when implementing such a design pattern, since template argument T can be used as Memento itself. In case you would not have generics or templates, Memento object might be needed.

And finally, where this pattern can be used actually? Probably, anywhere where restoration of some data is required. Real-world example could be the following probably: Switching between multiple accounts in the same app. Let us create a semi-toy code for that:

// This can work as Memento just perfectly.
class Account {
    public int Id { get; set; }
    public String Email { get; set; }
    public String SessionKey { get; set; }
}
 
// In real-world scenario, we might want to add the account somewhere.
// This will be the CareTaker
class IAccountManager
{
    void Add(Account item);
 
    Account Get(int id);
}
 
class AccountManager : IAccountManager
{
    private Map<int, Account> _accountsAccessible;
 
    public void Add(Account item) {
        _accountsAccessible[item.Id] = item;
    }
 
    public Account Get(int id) {
        return _accountsAccessible[id];
    }
}
 
// And finally, the Originator can be just some LoginService.
class LoginService
{
    private readonly IAccountManager _manager;
    private Account _account;
 
    public LoginService(IAccountManager manager)
    {
        _manager = manager;
    }
 
    public void Login(String email, String password)
    {
        // Some logging in logic.
        var id = <Some id extraction logic>(email, password);
        var sessionKey = <Some session key extraction logic>(email, password);
 
        _account = new Account(id, email, sessionKey);
 
        // In real-world, we will probably put the correct state as soon as it is retrieved.
        _manager.Add(_account);
    }
 
    public Account GetCurrentAccount()
    {
        return _account;
    }
 
    public void SetCurrentAccount(Account account)
    {
        _account = account;
    }
}

Then, somewhere LoginService can be used for switching between accounts, and for some other reasons that can be thought of.

So, I have shown you how the Memento Design Pattern can be implemented and used in the real-world scenarios.

Leave a Reply

Your email address will not be published. Required fields are marked *