4.2. Command

Maheshmaddi
4 min readApr 10, 2023

--

The Command pattern is a behavioral design pattern that encapsulates a request or action as an object, allowing for parameterization, queuing, logging, and undo functionality. It separates the object that invokes the action from the object that performs the action, promoting loose coupling and flexibility.

The Command pattern is typically used when:

  1. You want to decouple the object that invokes an action from the object that performs the action.
  2. You need to implement undo or redo functionality.
  3. You want to support queuing or logging of requests.
  4. You need to parameterize objects with different actions.

To implement the Command pattern, follow these steps:

  1. Define a command interface or abstract class that specifies the common methods for executing commands.
  2. Create concrete command classes that implement the command interface or extend the abstract class, providing the specific action and receiver object.
  3. Implement the execute method in the concrete command classes to invoke the appropriate action on the receiver object.
  4. Create an invoker class that maintains a reference to the command object and invokes its execute method.
  5. In the client code, create instances of the concrete command classes and pass them to the invoker object.

Here’s a simple example of the Command pattern in Java:

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

// Receiver class
class Receiver {
void action() {
System.out.println("Receiver action");
}
}

// Concrete command
class ConcreteCommand implements Command {
private Receiver receiver;

public ConcreteCommand(Receiver receiver) {
this.receiver = receiver;
}

@Override
public void execute() {
receiver.action();
}
}

// Invoker class
class Invoker {
private Command command;

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

void invoke() {
command.execute();
}
}

// Client code
public class Client {
public static void main(String[] args) {
Receiver receiver = new Receiver();
Command command = new ConcreteCommand(receiver);
Invoker invoker = new Invoker();

invoker.setCommand(command);
invoker.invoke(); // Outputs: "Receiver action"
}
}

In this example, the Command interface represents the common interface for executing commands. The ConcreteCommand class implements the Command interface and maintains a reference to a Receiver object. The Invoker class maintains a reference to the command object and invokes its execute method.

Advantages of the Command pattern:

  1. Decoupling: The pattern decouples the object that invokes an action from the object that performs the action, promoting flexibility and maintainability.
  2. Undo and redo functionality: The Command pattern enables the implementation of undo and redo functionality by storing the state before and after the command execution.
  3. Extensibility: New commands can be added easily without modifying existing code.

Disadvantages of the Command pattern:

  1. Increased complexity: The Command pattern introduces additional classes and objects, increasing the overall complexity of the code.

When using the Command pattern, consider its benefits and drawbacks carefully. Use the pattern when you want to decouple the object that invokes an action from the object that performs the action, implement undo and redo functionality, or support queuing or logging of requests. Be aware of the potential complexity introduced by the pattern and ensure that it is applied judiciously to maintain a clean and understandable codebase.

Use Case: Command Pattern for Home Automation System

Class Diagram Command Pattern for Home Automation System

In this use case, we will implement a simple home automation system that uses the Command pattern to control various devices like lights and fans. The Command pattern will allow us to decouple the requester (remote control) from the receiver (devices).

Here’s a Java code implementation:

  1. Command Interface:
public interface Command {
void execute();
void undo();
}

2. Concrete Command Classes (LightOnCommand and FanOnCommand):

public class LightOnCommand implements Command {
private Light light;

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

@Override
public void execute() {
light.on();
}

@Override
public void undo() {
light.off();
}
}

public class FanOnCommand implements Command {
private Fan fan;

public FanOnCommand(Fan fan) {
this.fan = fan;
}

@Override
public void execute() {
fan.on();
}

@Override
public void undo() {
fan. Off();
}
}

3. Receiver Classes (Light and Fan):

public class Light {
public void on() {
System.out.println("Light is on.");
}

public void off() {
System.out.println("Light is off.");
}
}

public class Fan {
public void on() {
System.out.println("Fan is on.");
}

public void off() {
System.out.println("Fan is off.");
}
}

4. Invoker Class (RemoteControl):

public class RemoteControl {
private Command command;

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

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

public void pressUndoButton() {
command. Undo();
}
}

5. Client Code (HomeAutomationDemo):

public class HomeAutomationDemo {
public static void main(String[] args) {
// Create receivers
Light livingRoomLight = new Light();
Fan livingRoomFan = new Fan();

// Create concrete commands
Command lightOnCommand = new LightOnCommand(livingRoomLight);
Command fanOnCommand = new FanOnCommand(livingRoomFan);

// Create invoker (remote control)
RemoteControl remoteControl = new RemoteControl();

// Set command and execute
remoteControl.setCommand(lightOnCommand);
remoteControl.pressButton(); // Output: Light is on.

// Set command and execute
remoteControl.setCommand(fanOnCommand);
remoteControl.pressButton(); // Output: Fan is on.

// Undo the last action
remoteControl.pressUndoButton(); // Output: Fan is off.
}
}

In this example, we implemented a home automation system that uses the Command pattern to control lights and fans. This approach allows us to easily extend the system to include more devices and commands without modifying existing classes.

Note: For complete list of design patterns click here

--

--