DEV Community

Hassan BOLAJRAF
Hassan BOLAJRAF

Posted on

1

C# | Command Design Pattern

Note
You can check other posts on my personal website: https://hbolajraf.net

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

Key Components:

  1. Command:

    • Defines an interface for executing a particular operation.
    • Typically includes an Execute method.
  2. ConcreteCommand:

    • Implements the Command interface.
    • Holds the information about the operation to be executed.
    • Invokes the operation through a receiver.
  3. Invoker:

    • Asks the command to execute the request.
    • Does not know how the request is handled.
  4. Receiver:

    • Knows how to perform the operation.
    • Can be any object that can perform the requested action.
  5. Client:

    • Creates a Command object and associates it with a Receiver.
    • Passes the command to the invoker.

Example in C#:

Let's consider a simple example of a remote control that can turn on and off devices:

1. Command Interface:

public interface ICommand
{
    void Execute();
}
Enter fullscreen mode Exit fullscreen mode

2. Concrete Commands:

public class LightOnCommand : ICommand
{
    private readonly Light _light;

    public LightOnCommand(Light light)
    {
        _light = light;
    }

    public void Execute()
    {
        _light.TurnOn();
    }
}

public class LightOffCommand : ICommand
{
    private readonly Light _light;

    public LightOffCommand(Light light)
    {
        _light = light;
    }

    public void Execute()
    {
        _light.TurnOff();
    }
}
Enter fullscreen mode Exit fullscreen mode

3. Receiver:

public class Light
{
    public void TurnOn()
    {
        Console.WriteLine("Light is ON");
    }

    public void TurnOff()
    {
        Console.WriteLine("Light is OFF");
    }
}
Enter fullscreen mode Exit fullscreen mode

4. Invoker:

public class RemoteControl
{
    private ICommand _command;

    public void SetCommand(ICommand command)
    {
        _command = command;
    }

    public void PressButton()
    {
        _command.Execute();
    }
}
Enter fullscreen mode Exit fullscreen mode

5. Client Code:

class Program
{
    static void Main()
    {
        Light livingRoomLight = new Light();
        ICommand livingRoomLightOn = new LightOnCommand(livingRoomLight);
        ICommand livingRoomLightOff = new LightOffCommand(livingRoomLight);

        RemoteControl remote = new RemoteControl();

        remote.SetCommand(livingRoomLightOn);
        remote.PressButton(); // Light is ON

        remote.SetCommand(livingRoomLightOff);
        remote.PressButton(); // Light is OFF
    }
}
Enter fullscreen mode Exit fullscreen mode

In this example, the RemoteControl acts as the invoker, and the commands (LightOnCommand and LightOffCommand) encapsulate the operations. The Light class is the receiver that knows how to perform the requested actions.

What Next?

The Command Pattern provides flexibility and decouples the sender and receiver of a request, making it easier to extend and maintain the code.

Image of Timescale

🚀 pgai Vectorizer: SQLAlchemy and LiteLLM Make Vector Search Simple

We built pgai Vectorizer to simplify embedding management for AI applications—without needing a separate database or complex infrastructure. Since launch, developers have created over 3,000 vectorizers on Timescale Cloud, with many more self-hosted.

Read full post →

Top comments (0)

Sentry image

See why 4M developers consider Sentry, “not bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more