A restaurant order decouples the customer (who requests food) from the chef (who prepares it). The waiter writes an order ticket — a Command object containing all the details — and places it in the kitchen queue. This allows orders to be queued, prioritized, logged, and even undone (canceled order). The Command pattern similarly encapsulates a request as an object, enabling parameterization, queuing, logging, and undo/redo operations.
Turns a request into a standalone object containing all information about the request. This lets you parameterize methods, delay execution, or queue operations.
- Command: Declares an interface for executing an operation, typically with an
execute()method. - ConcreteCommand: Defines a binding between a Receiver object and an action. Implements
execute()by invoking the corresponding operation on the Receiver. - Invoker: Asks the command to carry out the request. Optionally stores and manages commands for undo/redo.
- Receiver: Knows how to perform the actual work.
- Client: Creates ConcreteCommand objects and associates them with receivers.
#include <iostream>
#include <memory>
#include <stack>
#include <string>
class Light {
public:
void on() { std::cout << "Light is ON\n"; state_ = true; }
void off() { std::cout << "Light is OFF\n"; state_ = false; }
bool state() const { return state_; }
private:
bool state_ = false;
};
class Command {
public:
virtual ~Command() = default;
virtual void execute() = 0;
virtual void undo() = 0;
};
class LightOnCommand : public Command {
public:
explicit LightOnCommand(std::shared_ptr<Light> light) : light_(std::move(light)) {}
void execute() override { light_->on(); }
void undo() override { light_->off(); }
private:
std::shared_ptr<Light> light_;
};
class LightOffCommand : public Command {
public:
explicit LightOffCommand(std::shared_ptr<Light> light) : light_(std::move(light)) {}
void execute() override { light_->off(); }
void undo() override { light_->on(); }
private:
std::shared_ptr<Light> light_;
};
class RemoteControl {
public:
void setCommand(std::shared_ptr<Command> cmd) { command_ = std::move(cmd); }
void pressButton() {
if (command_) {
history_.push(command_);
command_->execute();
}
}
void pressUndo() {
if (!history_.empty()) {
auto cmd = history_.top();
history_.pop();
cmd->undo();
}
}
private:
std::shared_ptr<Command> command_;
std::stack<std::shared_ptr<Command>> history_;
};
int main() {
auto light = std::make_shared<Light>();
auto onCmd = std::make_shared<LightOnCommand>(light);
auto offCmd = std::make_shared<LightOffCommand>(light);
RemoteControl remote;
remote.setCommand(onCmd);
remote.pressButton();
remote.setCommand(offCmd);
remote.pressButton();
remote.pressUndo();
remote.pressUndo();
}class Light {
constructor() { this.isOn = false; }
on() { this.isOn = true; console.log('Light is ON'); }
off() { this.isOn = false; console.log('Light is OFF'); }
}
class LightOnCommand {
constructor(light) { this.light = light; }
execute() { this.light.on(); }
undo() { this.light.off(); }
}
class LightOffCommand {
constructor(light) { this.light = light; }
execute() { this.light.off(); }
undo() { this.light.on(); }
}
class RemoteControl {
constructor() {
this.command = null;
this.history = [];
}
setCommand(command) { this.command = command; }
pressButton() {
if (this.command) {
this.history.push(this.command);
this.command.execute();
}
}
pressUndo() {
const cmd = this.history.pop();
if (cmd) cmd.undo();
}
}
const light = new Light();
const onCmd = new LightOnCommand(light);
const offCmd = new LightOffCommand(light);
const remote = new RemoteControl();
remote.setCommand(onCmd);
remote.pressButton();
remote.setCommand(offCmd);
remote.pressButton();
remote.pressUndo();
remote.pressUndo();interface Command {
execute(): void;
undo(): void;
}
class Light {
private _isOn = false;
get isOn(): boolean { return this._isOn; }
on(): void { this._isOn = true; console.log('Light is ON'); }
off(): void { this._isOn = false; console.log('Light is OFF'); }
}
class LightOnCommand implements Command {
constructor(private light: Light) {}
execute(): void { this.light.on(); }
undo(): void { this.light.off(); }
}
class LightOffCommand implements Command {
constructor(private light: Light) {}
execute(): void { this.light.off(); }
undo(): void { this.light.on(); }
}
class RemoteControl {
private command: Command | null = null;
private history: Command[] = [];
setCommand(cmd: Command): void { this.command = cmd; }
pressButton(): void {
if (this.command) {
this.history.push(this.command);
this.command.execute();
}
}
pressUndo(): void {
const cmd = this.history.pop();
if (cmd) cmd.undo();
}
}
const light = new Light();
const onCmd = new LightOnCommand(light);
const offCmd = new LightOffCommand(light);
const remote = new RemoteControl();
remote.setCommand(onCmd);
remote.pressButton();
remote.setCommand(offCmd);
remote.pressButton();
remote.pressUndo();
remote.pressUndo();