The Command is an interesting pattern where two objects can communicate through commands. The advantage is decoupling the object from its behavior (commands).
In this example, the RemoteControl
creates slots with commands for Light
and Fan
named LightOnCommand
, LightOffCommand
, and FanSpeedCommand
.
#include <iostream>
#include <vector>
#include <memory>
#include <stack>
class Command {
public:
virtual void execute() = 0;
virtual void undo() = 0;
virtual ~Command() = default;
};
class Light {
private:
bool isOn = false;
public:
void turnOn() {
isOn = true;
std::cout << "๐ก Light is ON" << std::endl;
}
void turnOff() {
isOn = false;
std::cout << "๐ก Light is OFF" << std::endl;
}
bool getState() const { return isOn; }
};
class Fan {
private:
int speed = 0;
public:
void setSpeed(int s) {
speed = s;
if (speed == 0) {
std::cout << "๐ Fan is OFF" << std::endl;
} else {
std::cout << "๐ Fan speed set to " << speed << std::endl;
}
}
int getSpeed() const { return speed; }
};
class LightOnCommand : public Command {
private:
Light* light;
public:
LightOnCommand(Light* l) : light(l) {}
void execute() override {
light->turnOn();
}
void undo() override {
light->turnOff();
}
};
class LightOffCommand : public Command {
private:
Light* light;
public:
LightOffCommand(Light* l) : light(l) {}
void execute() override {
light->turnOff();
}
void undo() override {
light->turnOn();
}
};
class FanSpeedCommand : public Command {
private:
Fan* fan;
int newSpeed;
int previousSpeed;
public:
FanSpeedCommand(Fan* f, int speed) : fan(f), newSpeed(speed) {}
void execute() override {
previousSpeed = fan->getSpeed();
fan->setSpeed(newSpeed);
}
void undo() override {
fan->setSpeed(previousSpeed);
}
};
class NoCommand : public Command {
public:
void execute() override {
std::cout << "โ ๏ธ No command assigned" << std::endl;
}
void undo() override {
std::cout << "โ ๏ธ Nothing to undo" << std::endl;
}
};
class RemoteControl {
private:
std::vector<std::unique_ptr<Command>> onCommands;
std::vector<std::unique_ptr<Command>> offCommands;
static const int NUM_SLOTS = 4;
public:
RemoteControl() {
for (int i = 0; i < NUM_SLOTS; i++) {
onCommands.push_back(std::make_unique<NoCommand>());
offCommands.push_back(std::make_unique<NoCommand>());
}
}
void setCommand(int slot, std::unique_ptr<Command> onCommand,
std::unique_ptr<Command> offCommand) {
if (slot >= 0 && slot < NUM_SLOTS) {
onCommands[slot] = std::move(onCommand);
offCommands[slot] = std::move(offCommand);
}
}
void onButtonPressed(int slot) {
if (slot >= 0 && slot < NUM_SLOTS) {
onCommands[slot]->execute();
}
}
void offButtonPressed(int slot) {
if (slot >= 0 && slot < NUM_SLOTS) {
offCommands[slot]->execute();
}
}
};
int main() {
Light livingRoomLight;
Fan ceilingFan;
RemoteControl remote;
remote.setCommand(0,
std::make_unique<LightOnCommand>(&livingRoomLight),
std::make_unique<LightOffCommand>(&livingRoomLight)
);
remote.setCommand(1,
std::make_unique<FanSpeedCommand>(&ceilingFan, 3),
std::make_unique<FanSpeedCommand>(&ceilingFan, 0)
);
remote.onButtonPressed(0);
remote.offButtonPressed(0);
remote.onButtonPressed(1);
remote.offButtonPressed(1);
return 0;
}