The Command Pattern in Java

Introduction to the Command Pattern

Design pattern in a simple meaning, is a way to design reusable object-oriented code. We can think of ways to design our classes, interfaces, enums and their members so that the code is reusable but flexible.

There are 23 most important design patterns, pioneered by the book Design Patterns: Elements of Reusable Object-Oriented Software, written by Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides or Gang of Four for short. We will cover these design pattern one by one.

By original definition by the GoF, the Command pattern encapsulates a request as an object and thus lets us parameterize clients with different requests. The Command pattern also supports undoable operations.

Implementation of Command Pattern in Java

Now say we have the Door class with two simple actions, open and close:

public class Door {
  public Door() {}
  public void open(){
    System.out.println("The door is open");
  }
  public void close(){
    System.out.println("The door is close");
  }
}

When we want to close the Door or open the Door we simply call the open() or close() method. But the Command pattern requires us to encapsulate the request (open or close) as an object. We will create an interface Command that has only one method, the execute() method:

public interface Command {
  void execute();
}

Next to parameterize the request as an object, we will create two classes that implement the Command, and compose the Door object to them. First the DoorOpenCommand.java:

public class DoorOpenCommand implements Command{
  private final Door door;
  public DoorOpenCommand(Door door) {
    this.door = door;
  }
  public void execute() {
    door.open();
  }
}

Next, the DoorCloseCommand.java:

public class DoorCloseCommand implements Command{
  private final Door door;
  public DoorCloseCommand(Door door) {
    this.door = door;
  }
  public void execute() {
    door.close();
  }
}

Now in Test.java, we use the Command object to open and close the Door :D.

public class Test {
  public static void main(String[] args){
    Door door = new Door();
    //parameterise open request as an object.
    Command open = new DoorOpenCommand(door);
    open.execute();
    //parameterise close request as an object.
    Command close = new DoorCloseCommand(door);
    close.execute();
  }
}

The output will be exactly as what we presumed:

The door is open
The door is close

We can even abstract further. Say we have a remote controller class that controls a lot of doors, each door is a button in the remote.

We will create a RemoteController class:

public class RemoteControl {
  Command button;
  public void setCommand(Command command){
    button = command;
  }
  public void pressButton(){
    button.execute();
  }
}

Now in Test.java:

public class Test {
  public static void main(String[] args){
    Door door = new Door();
    RemoteControl control = new RemoteControl();
    var close = new DoorCloseCommand(door);
    var open = new DoorOpenCommand(door);
    control.setCommand(open);
    control.pressButton();
    control.setCommand(close);
    control.pressButton();
  }
}

The output will be the same:

The door is open
The door is close

Leave a Reply