The Command Design Pattern is a behavioral design pattern that turns a request into a stand-alone object. This object contains all the information about the request, allowing for easier parameterization of clients with different requests, queuing of requests, and logging of the requests. It also supports the undoable operations.

Concept:

  • Command: Represents a request and contains all the necessary information to execute that request. It typically includes an interface with an execute method.
  • ConcreteCommand: Implements the Command interface and binds together a specific command with its corresponding action.
  • Invoker: Asks the command to execute the request.
  • Receiver: Knows how to perform the operation associated with the command.
  • Client: Creates a concrete command and associates it with a receiver.

Example:

Let's consider a simple example where we have a light and want to control it using a remote control. We'll implement the Command Pattern to achieve this.

Command Interface:

# Command Interface
class Command
  def execute
    raise NotImplementedError, 'Subclasses must implement the execute method'
  end
end

Concrete Commands:

# Concrete Command: TurnOnCommand
class TurnOnCommand < Command
  def initialize(light)
    @light = light
  end

  def execute
    @light.turn_on
  end
end

# Concrete Command: TurnOffCommand
class TurnOffCommand < Command
  def initialize(light)
    @light = light
  end

  def execute
    @light.turn_off
  end
end

Receiver:

# Receiver: Light
class Light
  def turn_on
    puts 'Light is ON'
  end

  def turn_off
    puts 'Light is OFF'
  end
end

Invoker:

# Invoker: RemoteControl
class RemoteControl
  def initialize
    @command = nil
  end

  def set_command(command)
    @command = command
  end

  def press_button
    @command.execute if @command
  end
end

Client Code:

# Client code using the Command Pattern
light = Light.new

turn_on_command = TurnOnCommand.new(light)
turn_off_command = TurnOffCommand.new(light)

remote = RemoteControl.new

remote.set_command(turn_on_command)
remote.press_button  # Outputs: Light is ON

remote.set_command(turn_off_command)
remote.press_button  # Outputs: Light is OFF

In this example:

  • Command is the command interface.
  • TurnOnCommand and TurnOffCommand are concrete commands, each associated with turning the light on and off.
  • Light is the receiver, which knows how to perform the operations.
  • RemoteControl is the invoker, responsible for executing the command.

This pattern allows you to encapsulate a request as an object, parameterize clients with queues, requests, and operations, and support undoable operations. It's particularly useful in scenarios where you need to decouple senders and receivers of requests.