Hoinzey

Javascript. Kotlin. Android. Java

Design patterns: Memento

Ever make a bad decision in a game and load up a save ? Or fill in one of those forms that has 12 steps but if you muck up you can go back a few steps and everything previously filled in is still there ? Chances are you've encountered the memento pattern.


It is essentially an "Undo" button. It allows you to load a previous example of state. It consists of 3 main actors: the originator, the memento and the caretaker.


This can (probably) be found here


The originator

The originator is essentially our state object. It can create a snapshot or memento of its own state and can restore its state when given a memento. In our example, that will be a class which represents a Textview.


                    
    public class MementoTextView {

        private String text;

        public MementoTextView(String text) {
            this.text = text;
        }

        public Memento takeSnapshot() {
            return new Memento(this.text);
        }

        public void restore(Memento memento) {
            this.text = memento.text;
        }

        public static class Memento {
            ...
        }
    }
                

The takeSnapshot method allows us to create a snapshot of the state. The restore method can be used to restore state from a previous snapshot.

The memento

This represents a snapshot of your state. Therefore the fields described in this will often be a mirror of what is in your originator. You don't want to expose anything in this to your caretaker. That is why I have made it within my originator class.


                    
    public static class Memento {
        private final String text;

        private Memento(String text) {
            this.text = text;
        }
    }
                

The caretaker

The caretaker is responsible of creating snapshots and storing them to be used to restore state if needed. In this example I am using the Activity of an Android application as the caretaker.


It contains a list of the mementos and when a button is pressed it will use the memento to restore a TextView to an earlier state.


                    
    class MementoActivity : AppCompatActivity() {

        private val mementos = mutableListOf<MementoTextView.Memento>()

        private fun saveMemento() {
            et_memento?.let {
                val mementoTextView = MementoTextView(it.text.toString())
                mementos.add(mementoTextView.takeSnapshot())
                currentTextView = mementoTextView
            }
        }

        private fun undoChanges() {
            et_memento?.apply {
                val lastSave = mementos.last()
                currentTextView?.restore(lastSave)
                setText(currentTextView?.text)
                mementos.remove(lastSave)
            }
        }
    }
                

Again, this can (probably) be found here