Introduction to the Command Pattern

Introduction to the Command Pattern

Welcome to another essential part of our journey into Behavioral Patterns in C++ programming. In this lesson, we will explore the Command Pattern, a fundamental design pattern that is highly useful for promoting flexible and reusable code.

You might remember from previous lessons that behavioral design patterns help with object communication and responsibility distribution within your software. The Command Pattern is a great example that encapsulates a request as an object, thereby allowing users to parameterize clients with queues, requests, and operations.

What You'll Learn

In this lesson, you will master the Command Pattern by understanding its components and implementation. We'll break down the pattern into manageable parts and show you how to use it effectively.

To put it simply, the Command Pattern involves creating a command interface with an execute method. We then create concrete command classes that implement this interface, each representing a specific action. Finally, we'll integrate these commands with a request invoker to execute the actions.

Here's a brief illustration to give you a head start:

We start by defining a Light class that has on and off methods that print messages to the console:

class Light {
public:
    void on() {
        std::cout << "Light is on." << std::endl;
    }

    void off() {
        std::cout << "Light is off." << std::endl;
    }
};

Next, we create a Command interface with an execute method and two concrete command classes, LightOnCommand and LightOffCommand, that implement this interface. These classes encapsulate the Light object and execute its on and off methods, respectively:

class Command {
public:
    virtual void execute() = 0;
    virtual ~Command() {}
};

class LightOnCommand : public Command {
public:
    LightOnCommand(Light* light) : light(light) {}

    void execute() override {
        light->on();
    }

private:
    Light* light;
};

class LightOffCommand : public Command {
public:
    LightOffCommand(Light* light) : light(light) {}

    void execute() override {
        light->off();
    }

private:
    Light* light;
};

Finally, we create a RemoteControl class that sets and executes commands. The pressButton method calls the execute method of the command object:

class RemoteControl {
public:
    void setCommand(Command* command) {
        this->command = command;
    }

    void pressButton() {
        if (command) {
            command->execute();
        }
    }

private:
    Command* command = nullptr;
};

Now, we can test the Command Pattern by creating a Light object, LightOnCommand, LightOffCommand, and RemoteControl objects. We set the LightOnCommand and LightOffCommand as commands for the remote control and press the button to turn the light on and off:

int main() {
    Light* light = new Light();
    Command* lightOn = new LightOnCommand(light);
    Command* lightOff = new LightOffCommand(light);

    RemoteControl* remote = new RemoteControl();
    remote->setCommand(lightOn);
    remote->pressButton();
    remote->setCommand(lightOff);
    remote->pressButton();

    delete light;
    delete lightOn;
    delete lightOff;
    delete remote;
    return 0;
}

Let's understand the key components of the Command Pattern:

  • Command: This is an interface that declares an execute method. Concrete command classes implement this interface to execute specific actions.
  • Concrete Command: These classes implement the Command interface and encapsulate the receiver object. They execute the receiver's methods when the execute method is called. In the example above, LightOnCommand and LightOffCommand are concrete command classes.
  • Receiver: This is the object that performs the actual action. In the example, the Light class is the receiver that turns the light on or off.
  • Invoker: This is the object that sends a request to execute a command. In the example, the RemoteControl class is the invoker that sets and executes commands.
Sign up

Join the 1M+ learners on CodeSignal

Be a part of our community of 1M+ users who develop and demonstrate their skills on CodeSignal