Design Pattern Evangelist Blog

Smart pointers about software design

Command Design Pattern

Turn a function into a first-class citizen object so that it can do much more than before.


Picard Make It So

Command, Meh

I originally didn’t consider Command an Essential Design Pattern. I wasn’t even sure why it was listed as a design pattern originally. It just seemed like polymorphism.

This is the essence of the Command Design Pattern:

interface Command {
     void execute();
}

That’s it… but what is it?

Bob Martin changed my mind in the Command portion of his Agile Principles, Patterns, and Practices in C# book, Chapter 21, (O’Reilly and Amazon) and Clean Code: Design Patterns video. Episode 25 (Clean Coders and O’Reilly).

Objects are first-class citizens in Object-Oriented languages. There’s a popular saying in Java: Everything is an object in Java.

Functions are declared in classes as methods. They are not objects. They can be called directly, but that’s about it. They cannot be passed as arguments, added to data structures, etc. Other than calling them, there’s not much else we can do with them.

The Command Design Pattern allows us to wrap a function within a class, instantiate it as an object and then execute it through an Interface via polymorphism. By “objectifying” the function, it becomes a first-class citizen. A function wrapped within an object can do anything an object can do.

There is nothing difficult or sophisticated in the implementation of Command. It’s about intent, context and mindset. Once a function is an object, we can do much more with it. Here’s a simple example of a Command implementation:

class HelloWorld implements Command {
    void execute() {
        System.out.println("Hello World!");
    }
}

...

Command command = new HelloWorld();
command.execute();

Command can support parameters by passing them as constructor arguments. Here’s a more generalized version of the HelloWorld above, but this version prints any String:

class Printer implements Command {
    private final String text;

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

    public void execute() {
        System.out.println(text);
    }
}

...

Command printer = new Printer("Hello There World!");
printer.execute();

Command Decouples What from Whom

The examples above created instances of HelloWorld and Printer directly by invoking the new() operation. This violates the first design principle: Program to an interface rather than an implementation. We can use another Essential Design Pattern, Factory Method, and acquire the Command this way:

Command command = Commands.acquire("Hello World");
Command.execute();

Commands.acquire(String commandName) is a static method that encapsulates the specific class type from the code that uses it. Not only is the class type hidden, but the mechanism for choosing the class type is hidden. This decouples what is being executed from the code that is executing it.

A controller that could look something like this:

void processAction(Action action) {
    Command actionCommand = Commands.acquire(action);
    actionCommand.execute();
}

In the above, processAction(Action action) can handle any number of Actions as long as there’s a means to acquire a Command for a specific Action.

A feature can support many different actions. Each would have their own Action specific Command. Each class would be self-contained. Each could be more easily testable.

For more details, see The Evolution of Command Pattern (I): How Command Pattern has evolved overtime by Guowei Lv.

Command Decouples What from When

What if processAction(Action action) is executed on the user thread that requires fast response time? It’s possible for a Command to take a significant amount of time before it returns. We can’t block a user thread while waiting for a long running process.

Instead, we can schedule the Command to execute asynchronously on another thread by doing something like this:

void processAction(Action action) {
    Command actionCommand = Commands.acquire(action);
    processQueue.add(actionCommand);
}

This code adds the Command onto a queue which unblocks the processEvent(Action action). Another thread process will remove the Command from the queue and execute it.

Command Supports Undo and Redo

Command has a trick up its sleeve that functions do not have. Since Command is an object, it can have state, as was demonstrated in Printer implementation above with its text field attribute. A Command object can retain state about what it executed. It has the potential to undo what it executed. NOTE: Some functions cannot be undone. You can’t unring a bell.

Text processors have an undo option. If there’s a Command to make text bold, then there’s an undo to return it to its previous font. And if we’re allowing undo, why not redo as well? Here is generally how execute/undo/redo would work:

More details can be found in The Evolution of Command Pattern (II): How Command Pattern has evolved overtime also by Guowei Lv. I think there’s a typo in the implementation. The RedoCommand.undoable() returns false, when I think it should return true. He also does not clear the undoneStack when a new Command is executed. I don’t know if this is his oversight or whether I’m incorrect in my thinking that it should be cleared.

Command Processor Design Pattern

Most of what I’ve written about scheduling, undo, redo isn’t about Command directly. It’s more about how to leverage Command via the Command Processor Design Pattern, which is not in the Gang of Four catalog. It’s part of the Pattern-Oriented Software Architecture series, also known as POSA.

The Command Design Pattern provides a foundation from which the Command Processor Design Pattern can extend it.

Real-World Example with Java

Java’s Runnable interface is an example of Command only with different nomenclature. The structure is identical, but instead of execute(), it declares void run(). This is part of run’s description:

The general contract of the method run is that it may take any action whatsoever.

I love that definition. So unrestricted. Runnable allows developers the freedom to objectify “any action whatsoever.”

Runnable is often associated with Java’s Thread class. “Thread” appears in the Runnable documentation, which I disagree with. Runnable has no knowledge of or dependency upon Thread. It’s Thread that has knowledge of and a dependency upon Runnable.

A Runnable can be declared as a separate class, injected as an anonymous class or injected as a Lambda function. Anonymous classes and Lambda functions can be convenient, but unless they are extremely simple and obvious, I prefer a separate class so that the Runnable class can be unit tested.

The Thread class provides the framework within which to execute a Runnable in the JVM. Thread provides some control operations, but for the most part, Runnable’s execution within a Thread is encapsulated. Java has extended Thread management via these Executor interfaces:

The Executors class provides factory methods to acquire various ExecutorServices. Baeldung provides a brief tutorial for ExecutorServices: A Guide to the Java ExecutorService.

Runnable, Thread and ExecutorService can be a little daunting, but with knowledge of the Command and Command Processor Design Patterns they may be a little less daunting.

Summary

The Command Design Pattern objectifies a function. It allows us to decouple what a function does from who decides what is done and when it is done. It supports a more modular design. And the idea of a function as an object will be extended in more design patterns to come.

Additional References

I haven’t provided any detailed diagrams or implementations. There are many online resources with diagrams and implementations in different programming languages. Here are some free resources:

Here are some resources that can be purchased or are included in a subscription service:

Comments

Previous: Dems D’FFACTS

Next: Strategy Design Pattern

Home: Design Pattern Evangelist Blog