Why should I use the command design pattern while I can easily call required methods?

Daniel Newtown picture Daniel Newtown · Sep 16, 2015 · Viewed 22.1k times · Source

I am studying the command design pattern, and I am quite confused with the way of using it. The example that I have is related to a remote control class that is used to turn lights on and off.

Why should I not use the switchOn() / switchOff() methods of Light class rather than having separate classes and methods that eventually call switchOn / switchOff methods?

I know my example is quite simple, but that is the point. I could not find any complex problem anywhere on the Internet to see the exact usage of the command design pattern.

If you are aware of any complex real world problem that you solved that can be solved using this design pattern please share that with me. It helps me and future readers of this post to better understand the usage of this design pattern. Thanks

//Command
public interface Command {
  public void execute();
}

//Concrete Command
public class LightOnCommand implements Command {

  //Reference to the light
  Light light;

  public LightOnCommand(Light light) {
    this.light = light;
  }

  public void execute() {
    light.switchOn();        //Explicit call of selected class's method
  }
}

//Concrete Command
public class LightOffCommand implements Command {

  //Reference to the light
  Light light;

  public LightOffCommand(Light light) {
    this.light = light;
  }

  public void execute() {
    light.switchOff();
  }
}

//Receiver
public class Light {
  private boolean on;

  public void switchOn() {
    on = true;
  }

  public void switchOff() {
    on = false;
  }
}

//Invoker
public class RemoteControl {
  private Command command;

  public void setCommand(Command command) {
    this.command = command;
  }

  public void pressButton() {
    command.execute();
  }
}

//Client
public class Client {
  public static void main(String[] args) {
    RemoteControl control = new RemoteControl();
    Light light = new Light();
    Command lightsOn = new LightsOnCommand(light);
    Command lightsOff = new LightsOffCommand(light);

    //Switch on
    control.setCommand(lightsOn);
    control.pressButton();

    //Switch off
    control.setCommand(lightsOff);
    control.pressButton();
  }
}

Why should not I easily use code like the following?

 Light light = new Light();
 switch(light.command) {
  case 1:
    light.switchOn();
    break;
  case 2:
    light.switchOff();
    break;
 }

Answer

sprinter picture sprinter · Sep 16, 2015

The main motivation for using the Command pattern is that the executor of the command does not need to know anything at all about what the command is, what context information it needs on or what it does. All of that is encapsulated in the command.

This allows you to do things such as have a list of commands that are executed in order, that are dependent on other items, that are assigned to some triggering event etc.

In your example, you could have other classes (e.g. Air Conditioner) that have their own commands (e.g. Turn Thermostat Up, Turn Thermostat Down). Any of these commands could be assigned to a button or triggered when some condition is met without requiring any knowledge of the command.

So, in summary, the pattern encapsulates everything required to take an action and allows the execution of the action to occur completely independently of any of that context. If that is not a requirement for you then the pattern is probably not helpful for your problem space.

Here's a simple use case:

interface Command {
    void execute();
}

class Light {
    public Command turnOn();
    public Command turnOff();
}

class AirConditioner {
    public Command setThermostat(Temperature temperature);
}

class Button {
    public Button(String text, Command onPush);
}

class Scheduler {
    public void addScheduledCommand(Time timeToExecute, Command command);
}

Then you can do things such as:

new Button("Turn on light", light.turnOn());
scheduler.addScheduledCommand(new Time("15:12:07"), airCon.setThermostat(27));
scheduler.addScheduledCommand(new Time("15:13:02"), light.turnOff());

As you can see the Button and Scheduler don't need to know anything at all about the commands. Scheduler is an example of a class that might hold a collection of commands.

Note also that in Java 8 functional interfaces and method references have made this type of code even neater:

@FunctionalInterface
interface Command {
    void execute();
}

public Light {
    public void turnOn();
}

new Button("Turn On Light", light::turnOn);   

Now the methods that are turned into commands don't even need to know about commands - as long as they have the correct signature you can quietly create a anonymous command object by referencing the method.