Here, we will talk about undoing commands to change to course of history......

The Command Pattern, as described in one of the earlier blogs, has a wide variety of applications, one of which is the most famous text-editing command - Undo.
Usually, to implement Undo mechanisms, the Memento Pattern is used but here's the thing -

  1. Memento stores the history objects as they are without any manipulation or processing or abstraction. So, once the size of history objects starts to become large (eg : video, images) , the space and time complexities of this pattern become hugely inefficent.
  2. Which is why, in most modern applications, Command Pattern is used to implement undo because what Command Pattern stores as history object is just some logic that helps restore the actual history object when the Undo command is executed.
    This logic is pretty lightweight so space and time complexities are both optimized.

To know more about the fundamentals about the Memento and the Command Pattern, be sure to check out these blogs by me on the same !

Command Pattern | Java
Using the command pattern to understand how most modern frameworks implement the right balance of abstraction and control
Memento Pattern
An excerpt on implementing undo mechanism in software applications using the Memento Pattern

Basic UML of Command Pattern

Project Unified Modelling Language (UML) Diagram

UML Explanation....

At its core, the command pattern consists of 4 interacting bodies

BodyFunction
InvokerInteracts with the interface to call a specific function on the receiver side
CommandIt's the interface establishes and controls communication between the sender and the receiver. It declares an execute( ) method
ReceiversClasses that expose methods that hold the actual implementation logic of a receiver service (eg : AddService, AuthService etc.)
ConcreteCommandA child class of the interface that defines the execute( ) method and which receiver service it shall call.

Resources

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

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

Project Description

Here, in this article, we will be building a simple application that implements the Undo Mechanism the way most modern applications like Google Suite, Adobe Creative Cloud and many more services use, using the Command Pattern method.
You will understand how this abstraction not only makes code more scalable, but also more optimized in terms of space and time

command-undo-concept

command-undo-implementation

Implementing the Command (Interface)

The top level parent interface that establishes and manages communication between the sender and receiver
  1. On some request from sender, it creates a Command object
  2. Also, it declares the execute( ) method which shall be defined on the receiver end to run the logic that answers the sender's request.
public interface Command {
    void execute();
}
Command.java

Implementing the UndoableCommand class

This is just a child interface of the Command class that simply extends the functionality of the prototype any classes extending this class (i.e. classes having undo feature on them) must have.
public interface UndoableCommand extends Command{
    void unexecute();
}
UndoableCommand.java

Tracking the history of commands

A simple class that is just tracking the history of the current Command object, with respect to which commands were run on it, so we can undo commands easily.
public class History {
    private Deque<UndoableCommand> commands = new ArrayDeque<>();

    public void push(UndoableCommand command){
        commands.add(command);
    }

    public UndoableCommand pop(){
        return commands.remove();
    }

    public Integer size(){
        return commands.size();
    }
}
History.java

Implementing the Receiver - BoldCommand

These is a simple class that exposes methods holding the implementation logic to change history of the current command object based on a do or and undo

Method Name Function
execute( ) Method for implementing 2 things - (1) Making modifications to the 'content' string of the current object (2) Pushing the newly modified command object to the current object's history (3) Tracking the previous state of the 'content' string
unexecute( ) Method for implementing the authentication of an existing user
public class BoldCommand implements UndoableCommand {
    public HtmlDoc document;
    public String prevContent;
    public History history;

    public BoldCommand(HtmlDoc document, History history) {
        this.document = document;
        this.history = history;
    }

    @Override
    public void execute() {
        prevContent = document.getContent();
        document.makeBold();
        history.push(this);
    }

    @Override
    public void unexecute() {
        document.setContent(prevContent);
    }
}
BoldCommand.java

Implementing the ConcreteCommand - UndoCommand

A child class of the Command interface.

It does 2 things :

  1. It keeps track of the History of commands and changes it if an UndoableCommand's execute( ) method is run
public class UndoCommand implements Command{
    private History history;

    public UndoCommand(History history) {
        this.history = history;
    }

    @Override
    public void execute() {
        if (history.size()>0){
            history.pop().unexecute();
        }
    }
}
UndoCommand.java

Implementing the Invoker

A simple class that gives out an object that developers using this pattern use to execute some receiver function.
  1. Here, we simply create a HTMLDoc class that manages the state of a simple string ('con) - whether it is in bold or not.
  2. makeBold( ) - Command that calls makes the string content bold.
  3. On activating this makeBold( ) function object (instance of our HTMLDoc class), a Command object is created and the execute( ) method is called on it
public class HtmlDoc {
    public String content;

    public void makeBold(){
        this.content = "<b>" + this.content + "</b>";
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }
}
HTMLDoc.java

Using this pattern in our application

Import all the necessary classes and modules into main.java for a final showdown of our application ! Here, I'll be show the adding the  !

var document = new HtmlDoc();
var historyOfCmds = new com.ankit.command.undo.History();
var boldCommand = new BoldCommand(document,historyOfCmds);
document.setContent("Namaskar !");
System.out.println(document.getContent());

boldCommand.execute();
System.out.println(document.getContent());

var undoCommand = new UndoCommand(historyOfCmds);
undoCommand.execute();
System.out.println(document.getContent());

Conclusion

Congrats on unlocked the secret of how most modern apps reverse your actions. You should feel pretty comfortable now developing the your own simple apps like text editors, with undo functionalities in a that contain the right balance of abstraction and control. Until next time...‌

I shall also be writing some content on using the Command Pattern to implement Composite Commands and Undo, Redo functions so do check them out !!‌

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.