logo

Achieve Ultimate Excellence

Command Design Pattern - Encapsulates a Request as an object for Execution.

Introduction

In software development, design patterns are invaluable tools that enable us to solve common problems and maintain clean and maintainable code. One such design pattern is the Command design pattern, which is categorized under the behavioral patterns. The Command pattern encapsulates a request as an object, allowing you to parameterize clients with different requests, queue or log requests, and undo operations easily. In this blog post, we will delve into the details of the Command design pattern and explore a practical example of its implementation in Java.

Understanding the Command Design Pattern

The Command design pattern follows the principle of encapsulation, where a request is wrapped within an object, thus decoupling the sender and receiver. This provides a level of abstraction, making it easier to extend and modify functionality without altering the existing code.

Key Components of the Command Pattern

  1. Command: This is an interface that declares the execution method, typically named execute(), which all concrete command classes must implement.

  2. Concrete Command: These are classes that implement the Command interface and encapsulate a specific action along with the necessary receiver object (the one that performs the actual action).

  3. Invoker: The invoker is responsible for triggering the command's execution. It does not know anything about the concrete command but holds a reference to the command object.

  4. Receiver: The receiver is the object that performs the actual action requested by the command. It knows how to carry out the operation associated with the command.

Example: Implementing the Command Pattern in Java

For our example, let's create a simple home automation system where we have two devices: a Light and a Fan. We'll implement commands to turn them on and off.

1. Command Interface

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

2. Concrete Command Classes

// LightOnCommand.java
public class LightOnCommand implements Command {
    private Light light;

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

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

// LightOffCommand.java
public class LightOffCommand implements Command {
    private Light light;

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

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

// FanOnCommand.java
public class FanOnCommand implements Command {
    private Fan fan;

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

    public void execute() {
        fan.turnOn();
    }
}

// FanOffCommand.java
public class FanOffCommand implements Command {
    private Fan fan;

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

    public void execute() {
        fan.turnOff();
    }
}

3. Receiver Classes

// Light.java
public class Light {
    public void turnOn() {
        System.out.println("Light is ON");
    }

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

// Fan.java
public class Fan {
    public void turnOn() {
        System.out.println("Fan is ON");
    }

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

4. Invoker Class

// RemoteControl.java
public class RemoteControl {
    private Command command;

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

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

5. Client Code

public class Client {
    public static void main(String[] args) {
        RemoteControl remoteControl = new RemoteControl();

        // Creating receiver objects
        Light livingRoomLight = new Light();
        Fan livingRoomFan = new Fan();

        // Creating command objects with receivers
        LightOnCommand livingRoomLightOn = new LightOnCommand(livingRoomLight);
        LightOffCommand livingRoomLightOff = new LightOffCommand(livingRoomLight);
        FanOnCommand livingRoomFanOn = new FanOnCommand(livingRoomFan);
        FanOffCommand livingRoomFanOff = new FanOffCommand(livingRoomFan);

        // Setting commands to invoker
        remoteControl.setCommand(livingRoomLightOn);
        remoteControl.pressButton(); // Light is ON

        remoteControl.setCommand(livingRoomFanOn);
        remoteControl.pressButton(); // Fan is ON

        remoteControl.setCommand(livingRoomLightOff);
        remoteControl.pressButton(); // Light is OFF

        remoteControl.setCommand(livingRoomFanOff);
        remoteControl.pressButton(); // Fan is OFF
    }
}

Conclusion

The Command design pattern is a powerful way to decouple sender and receiver objects, allowing for extensible and flexible code. By wrapping requests in objects, it enables us to implement features like undo, redo, and queuing of commands effortlessly. Moreover, the Command pattern promotes clean and maintainable code by adhering to the principles of encapsulation and abstraction.

In this blog post, we provided a detailed explanation of the Command design pattern and demonstrated its implementation in Java through a practical home automation system example. Incorporating this pattern in your projects can lead to more modular and manageable code, improving overall software quality and maintainability.

avatar
Article By,
Create by
Browse Articles by Related Categories
Browse Articles by Related Tags
Share Article on:

Related posts

Related posts