Implement undo mechanisms in our classes

The Memento Pattern is one of the most well-known and commonly used Structural Design Patterns.

It uses Object Oriented Programming principles in a 3 class setup to easily implement undo mechanisms used in most software editors, ranging from VSCode and Google Docs to Photoshop and most browsers' go-back features.

memento

Resources

The source code for all prominent design patterns has been properly implemented and documented in this GitHub repostitory by me.

undo

crew-guy/Design-Patterns
A collection of the design patterns, implemented in java, as originally created by the GoF - crew-guy/Design-Patterns

Implementing the History class

Also known as the Caretaker


Type Name Function
Variable 'states' An array of objects (implemented as a stack) where each object extends the EditorState class
Methods pop Returns the most recent aka state object stored in the states array. (top of the stack)
push Adds a new state to the states list
public class History {
  public List<EditorState> states = new ArrayList<>();

  public void push(EditorState state){
    states.add(state)
  }
  public void pop(){
    var lastIndex = states.size() - 1;
    var lastState = states.get(lastIndex);
    states.remove(lastIndex);
    return lastState;
  }
}

Implementing the EditorState class

Also known as the Memento


Type Name Function
Variables state An object having a content property
Methods getContent Retrieves the content (string) of the state object passed to it from the states list in the History class
public class EditorState {
  private final String = content;

  // Constructor
  public EditorState(String content){
    this.content = content;
  }

  public String getContent(){
    return this.content
  } 
}

Implementing the Editor class

Also known as the Originator


Type Name Function
Variable content Simple string that is passed from the user input
Methods createState Creates an EditorState object using the content string
restore Retrieves the content as a string from the History class using EditorState's getContent() method
getContent Getter for the content variable
setContent Setter for the content variable
public class Editor {
  private String content;

  public String restore(EditorState state){
    this.content = state.getContent();
  }

  public EditorState createState(){
    return new EditorState(this.content);
  }

  public String getContent(){
    return this.content;
  }

  public void setContent(content){
    this.content = content
  }

Using this pattern

Import and call the following in your main class :

class Main {
  public static void main(String[] args) {
    var editor = new Editor()
    var history = new History()

    editor.setContent("a")
    history.push(editor.createState())

    editor.setContent("b")
    history.push(editor.createState())

    editor.setContent("c")
    history.push(editor.createState())

    editor.restore(history.pop())
  }

Conclusion

Congrats on unlocked the secret of how a computer reverses time. You should feel pretty comfortable now developing the undo and redo functionalities in your applications. Until next time...

eye

References..

Whatever I have learnt and implemented here in code as well as the explanation is all from the teachings of the brilliant Mosh Hamedani and his course on Design Patterns which I would recommend you to take if you are really interested in exploring the beauty of Object Oriented Programming

The Ultimate Design Pattern Series
Ace your coding job interview. Learn to write maintainable and extensible code.