Command Design Pattern

Design Pattern Tutorial Series

Command Design Pattern in Java - 5-Step Guide

The Command Pattern uses an object to represent a method (aka command), which can be call upon later by an invoker. This means that it will be possible to send methods around the system and call upon them whenever they are needed. 

It is understandably categorized as a behavioral design pattern, since it manages the functionality of the invoker.

It is a convenient pattern to understand as it can be used as a versatile utility in many scenarios and can dramatically improve the level of clean code.

NOTE: If you are working with a language version, which has enabled lambda functions, then I would argue that the command pattern is history to you.

Lambda functions enable you to create and pass methods around based on inbuilt interfaces. It is essentially the command pattern, but with additional features.

Table of Contents

command-design-pattern-overview-INTEGU

Step 1 - The Objective

The objective for this tutorial will be to create an online system simulating a library.

We want to be able to gather a collection of books and borrow and return them in bulks. Each book of cause has its unique content, but they all share the same basic rule, they can be borrowed from and returned to the library.

In a library you would always collect all the books that you wanted to borrow and afterwards register them all at the same time as “rented” at the service desk. The same goes for when you return the books. Therefore, the system should only require one method call to borrow or return a whole collection of books, since it would be the most accurate representation of reality.

Additionally, we need to know the book’s state of availability when we borrow and return it. This will ensure that the book has the correct state at the appropriate point of time. We do not want the books to become unavailable until someone actually borrows them.

command-design-pattern-objective-INTEGU

Step 2 - Expanded Argument List or Premature State Change

Usually, I would attempt to come up with a simple scenario which highlights the primary disadvantage of not utilizing the given pattern.

But in this case, I believe that one of the strongest advantages of the command pattern is the convenience of having a method stored as an object, which really only shines in a larger system. Since building a large system for the purpose of a simple tutorial ruins the intension, I had to drop the code sample.

Therefore, I will only explain the disadvantages of not utilizing the command pattern through theory and illustrations.

Imagine that the methods for borrowing and returning books were stored in classes without any direct relationship to the context in which we want to use it.

In this case we would somehow have to make room, in all the argument lists of the methods path from the invoked method to the place where we would need it.

command-design-pattern-disadvantage-pass-through-classes-INTEGU

This is definitely not the cleanest coding approach. It may even end up confusing future developers why these arguments have been added to these unrelated methods.

On the other hand, let’s say we were to simply just call the method and pass on the result to the part of the system which required it. In this case, we would not know whether it would be the correct result when it reached its target.

In our scenario we could imagine two visitors.

One of them is collecting all the books in their online cart. This person required a lot of books and is taking a long time checking out several books.

Meanwhile, we have another visitor who is just there to get one book. Unfortunately, the book is part of the first visitor’s collection.

When the second visitor goes to the checkout to borrow the book, they cannot have it because the book’s state of availability was changed prematurely by the first visitor.

This is of cause a matter of how we want to design the system, but in this specific
scenario it contradicts one of the requirements.

command-design-pattern-disadvantage-INTEGU

Step 3 - Concept of the Command Pattern

The concept of the command design pattern is, as mentioned in the introduction, to enable objects to store methods.

This is done by taking the object of the desired method, aka. the invoker and inserting it into a command class. The command class can then execute the desired method of the inserted object at any time.

The thing to note is that each command class implements the command interface, which only declares one method, the execute method.

The command class, which implements the interface, is only intended to call one specific method of the inserted object within the execute. This means that for each method that we want to call, an individual command class must be created. For this reason, you will often see the command class take the name of the method that they are calling. (e.g. BorrowCommand)

This pattern gives us several advantages. Firstly, we can move methods around the system, and call them whenever needed.

Secondly, this also means that we get the result of the method call with the current state of the system and not with the state in which it was when we stored the method.

Finally, we are also able to swap between the commands, since they all implement the same command interface. We can therefore rely on them to have the execute method.

command-design-pattern-advantage-INTEGU

Practically for our scenario, this means that we will create a few book classes, which extends the Book abstract class. The class declares that all books can be borrowed and returned to the library.

Additionally, since it is an abstract class, we can also declare a boolean field to store the availability of the book.

Then we are going to create the “borrowFromLibrary“- and “returnToLibrary” command classes, which both implement the command interface.

Because all books objects extend the book abstract class, we can use the concrete command classes to work with various types of books.

As a final remark, we create a book list object inside the concrete command classes. This allows us to fulfill the final objective of being able to handle all invoked methods simultaneously (borrow or rent).

This is all we need in order to utilize the command pattern. Now let’s look at the class diagram of this setup.

Step 4 - Class Diagram (UML)

As we have already explained in the previous section, the command pattern consists of two parts, the command and the invoker.

The invoker is the object containing the method which the command object wants to call. In our case, that would be the book class.

Note how both the command- and book object extends / implements from their respective abstract class / interface. This enables a potential for a decoupled code structure, in which we never have to work with the concrete objects.

Although the class diagram looks rather simple, it can prove extremely useful.

command-design-pattern-class-diagram-INTEGU

Step 5 - Code (Java)

Given that code is sometimes difficult to learn through concepts and theory, I provide the code for the example.

Hopefully, this will be sufficient for you to learn to identify and implement the command pattern in your future endeavors as a software developer.

Book (Invoked Methods)

public abstract class Book {
    boolean available = true;
    abstract void borrowFromibrary();
    abstract void returnToLibray();
}
public class DesignPatternsBook extends Book {
        @Override
        public void borrowFromibrary() {
            if(available){
                System.out.println("The Design Patterns book has " +
                        "been borrowed to the library." + "n");
                available = !available;
            }else{
                System.out.println("It was not possible to borrow " +
                        "the Design Patterns book." + "n");                
            }
        }
        @Override
        public void returnToLibray() {
            if(!available) {
                System.out.println("The Design Patterns book has " +
                        "been returned to the library." + "n");
                available = !available;
            }else{
                System.out.println("It was not possible to return " +
                        "the Design Patterns book" + "n");
            }
        }
}

Commander

public interface Command {
    void execute();
}
import java.util.ArrayList;
import java.util.List;
public class BorrowCommand implements Command{
    private List book = new ArrayList<>();
    public void takeBook(Book book){
        this.book.add(book);
    }
    @Override
    public void execute() {
       book.forEach(Book::borrowFromibrary);
    }
}

How To Use The Strategy Pattern

public class Main {
    public static void main(String[] args) {
        ScrumBook scrumBook = new ScrumBook();
        JavaBook javaBook = new JavaBook();
        DesignPatternsBook designPatBook = new DesignPatternsBook();
        BorrowCommand borrowCommand = new BorrowCommand();
        borrowCommand.takeBook(scrumBook);
        borrowCommand.takeBook(javaBook);
        borrowCommand.takeBook(designPatBook);
        executeCommand(borrowCommand);
        ReturnCommand returnCommand = new ReturnCommand();
        returnCommand.takeBook(javaBook);
        returnCommand.takeBook(designPatBook);
        executeCommand(returnCommand);
    }
    private static void executeCommand(Command command) {
        command.execute();
    }
}

Recommended Reading

Article

  • Theoretical walkthrough – Source Making – Blog
  • Practical walkthrough – Tutorialspoint – Blog
  • Practical walkthrough – Springframework Guru – Blog
  • Why Lambda removes the need for the Command Pattern – Understanding Lambda-enabled Design Patterns – Blog

Tools

  • Camtasia – Used for illustrations – Camtasia

Books

Video Tutorial 

    • Theoretical (based on “Head-First: Design Patterns”) – Christopher Okhravi – YouTube
    • Practical – Derek Banas – YouTube

About

Hi, I'm the Author

My name is Daniel H. Jacobsen and I’m a dedicated and highly motivated software developer with a masters engineering degree within the field of ICT. 

I have through many years of constantly learning and adapting to new challenges, gained a well-rounded understanding of what it takes to stay up to date with new technologies, tools and utilities. 

The purpose of this blog is to share both my learnings and knowledge with other likeminded developers as well as illustrating how these topics can be taught in a different and alternative manner.

If you like the idea of that, I would encourage you to sign up for the newsletter.

Cheers! 🍺

Didn't Find What You Were Looking For?

Generic selectors
Exact matches only
Search in title
Search in content
Search in posts
Search in pages
Scroll to Top