Command Design pattern

 Command Pattern is a behavioral design pattern that turns a request into a stand-alone object. This pattern decouples the sender and receiver of the request. It is particularly useful when you want to parameterize objects with operations, queue requests, or allow undo functionality.

Command Pattern Explanation:

In the Command Pattern, the request is encapsulated as an object, allowing for parameterization of clients with queues, requests, and operations. The key components are:

  1. Command: An interface or abstract class that declares a execute() method.
  2. ConcreteCommand: A class that implements the Command interface and defines the binding between a receiver and the action.
  3. Invoker: A class that asks the command to execute the request.
  4. Receiver: A class that knows how to perform the operations associated with the request.
  5. Client: The class that creates the command and sets its receiver.

Example:

Let’s implement a simple example where the Command Pattern is used to perform actions like turning on and off a light.


1. Command Interface:

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

2. Concrete Command Classes:

These are concrete implementations of the Command interface, representing actions to be executed.

java
// Concrete Command to turn the light on public class LightOnCommand implements Command { private Light light; // Receiver of the command public LightOnCommand(Light light) { this.light = light; } @Override public void execute() { light.turnOn(); // Invokes the receiver's method } } // Concrete Command to turn the light off public class LightOffCommand implements Command { private Light light; // Receiver of the command public LightOffCommand(Light light) { this.light = light; } @Override public void execute() { light.turnOff(); // Invokes the receiver's method } }

3. Receiver Class:

The Receiver is the class that actually knows how to perform the action.

java
// Receiver class: Light public class Light { public void turnOn() { System.out.println("The light is ON."); } public void turnOff() { System.out.println("The light is OFF."); } }

4. Invoker Class:

The Invoker is responsible for calling the execute() method on the command object.

java
// Invoker class: RemoteControl public class RemoteControl { private Command command; public void setCommand(Command command) { this.command = command; } public void pressButton() { command.execute(); // Executes the command } }

5. Client Code:

Finally, we use the Client to wire everything together and make the requests.

java
// Client code public class CommandPatternDemo { public static void main(String[] args) { // Receiver Light light = new Light(); // Concrete Commands Command lightOn = new LightOnCommand(light); Command lightOff = new LightOffCommand(light); // Invoker RemoteControl remote = new RemoteControl(); // Turn the light on remote.setCommand(lightOn); remote.pressButton(); // Output: The light is ON. // Turn the light off remote.setCommand(lightOff); remote.pressButton(); // Output: The light is OFF. } }

Explanation:

  1. Command Interface: Defines a method execute(), which is implemented by concrete command classes.
  2. ConcreteCommand: LightOnCommand and LightOffCommand implement the execute() method. These classes are responsible for invoking the corresponding actions on the Receiver (in this case, the Light class).
  3. Receiver: The Light class has the actual business logic for turning the light on and off.
  4. Invoker: The RemoteControl class holds a reference to a Command object and calls execute() on it when a button is pressed.
  5. Client: The CommandPatternDemo class sets everything up by creating the command objects and associating them with the invoker.

Output:

vbnet
The light is ON. The light is OFF.

Why Use the Command Pattern?

  • Decoupling the sender and receiver: The sender (e.g., RemoteControl) doesn't need to know anything about the receiver (e.g., Light). It simply calls execute() on the command.

  • Extensibility: Adding new commands (like turning the light on in different ways, or adding a fan control) is easy. You can create new command classes without modifying existing code.

  • Undo/Redo functionality: The Command pattern can be extended to support undo and redo by keeping track of executed commands and their previous states.

  • Queueing requests: Commands can be queued for execution or logged.

+------------------+
|    Command      |◄──────────+
|------------------|           |
| + execute()     |           |
+------------------+           |
         ▲                     |
         |                     |
+-------------------+    +-------------------+
| LightOnCommand   |    | LightOffCommand   |
|-------------------|    |-------------------|
| - light: Light   |    | - light: Light   |
|-------------------|    |-------------------|
| + execute()      |    | + execute()      |
+-------------------+    +-------------------+
         ▲                     ▲
         |                     |
+------------------+   +------------------+
|      Light       |   |  RemoteControl   |
|------------------|   |------------------|
| + turnOn()      |   | - command: Command |
| + turnOff()     |   |------------------|
+------------------+   | + setCommand(cmd) |
                       | + pressButton()  |
                       +------------------+
                                ▲
                                |
                       +---------------------+
                       | CommandPatternDemo  |
                       |---------------------|
                       | + main(args)        |
                       +---------------------+

Comments

Popular posts from this blog

Archunit test

Hexagonal Architecture

visitor design pattern