Sobes.tech
Middle+

Do you use the Command pattern in your work?

sobes.tech AI

Answer from AI

Yes, I use the Command pattern in my work.

The Command pattern encapsulates a request as an object, allowing parameterization of clients with different requests, queuing or logging requests, and supporting undo operations.

I apply it when:

  • It is necessary to parameterize objects with an action.
  • Operations need to be queued, scheduled, or logged.
  • An undo or redo mechanism is required.
  • Low-level operations should be adapted for high-level components.

Examples of usage:

  • Graphical user interface systems where commands correspond to user actions (e.g., "Insert", "Copy").
  • Transaction management systems.
  • Distributed systems and message queues.
  • Macro or script implementations.

Structurally, the pattern includes:

  • Command: an interface or abstract class declaring the method for executing an operation.
  • ConcreteCommand: a specific implementation of Command, linking the receiver with an action. Contains a reference to Receiver.
  • Client: creates a ConcreteCommand object and sets the receiver.
  • Invoker: calls the command execution. It holds a Command object.
  • Receiver: the object that performs the actual action.

Example: A simple implementation of a command to toggle a light.

// Command interface
interface Command {
    void execute();
    void undo(); // For undo support
}

// Receiver
class Light {
    private boolean isOn = false;

    public void turnOn() {
        isOn = true;
        System.out.println("Light is ON");
    }

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

// Concrete command to turn on the light
class TurnOnLightCommand implements Command {
    private Light light;

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

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

    @Override
    public void undo() {
        light.turnOff(); // Undo turn on
    }
}

// Concrete command to turn off the light
class TurnOffLightCommand implements Command {
    private Light light;

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

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

    @Override
    public void undo() {
        light.turnOn(); // Undo turn off
    }
}

// Invoker
class RemoteControl {
    private Command command;

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

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

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

// Client
public class Client {
    public static void main(String[] args) {
        Light livingRoomLight = new Light(); // Receiver

        Command turnOn = new TurnOnLightCommand(livingRoomLight); // Concrete command
        Command turnOff = new TurnOffLightCommand(livingRoomLight);

        RemoteControl remote = new RemoteControl(); // Invoker

        remote.setCommand(turnOn);
        remote.pressButton(); // Light is ON

        remote.pressUndoButton(); // Light is OFF

        remote.setCommand(turnOff);
        remote.pressButton(); // Light is OFF

        remote.pressUndoButton(); // Light is ON
    }
}

Comparison table with other patterns:

Pattern Main purpose Difference from Command
Strategy Defines a family of algorithms and encapsulates each one. Encapsulates an entire algorithm (what to do), whereas Command is a specific action (how to do).
Observer Defines a one-to-many dependency between objects. Relates to notifications about state changes, not request execution.
Memento Saves and restores an object's state without breaking encapsulation. Used for saving state, not for encapsulating actions.
Do you use the Command pattern in your work? — Java - sobes.tech