Command Pattern:
Encapsulates a request as an object, thereby letting you parametrize other objects with different requests, queue or log requests, and support undo-able operations.
Command Pattern is usually used in the scenario that we want to perform multiple operations on the same data. For example, in a image processor, we could choose to rotate, flip or invert colors of the photo or even to undo the operations. It also allows to decouple the requester from an action from the object that actually performs the action.
Example without using Command Pattern:
class imageProcess {
private:
bool rotateImage;
bool flipImage;
bool deleteImage;
public:
void inputHandler() {
if(rotateImage) {rotate();}
else if(flipImage) {flipImage();}
else if(deleteImage) {deleteImage();}
}
};
The drawback is quite clear: we will have to write a lot of condition code for each action. Also, if we have more commands, we will have to change the existing code very often. To solve this problem, there is a mechanism that all the actions can somehow be handled polymorphically which makes the code clean and less error prone. This isCommand Pattern.
1: Allows to store a lists of code that is executed at a later time or many times.
2: Client says that a specific Command to run when execute() is called on one of the encapsulated objects. (dynamic binding)
3: An object called the "Invoker" transfers this Command to another Object called a "Receiver" to execute the right code.
For example:
TurnTVOn --> Device Botton(invoker) --> TurnTVOn --> Television.TurnTVOn() (receiver)
#include "../header.h"
using namespace std;
class Command {
public:
virtual void execute() = 0;
};
class ElectronicDevice {
public:
virtual void on() = 0;
virtual void off() = 0;
virtual void volumnUp() = 0;
virtual void volumnDown() = 0;
};
class TurnTvOn : public Command {
private:
ElectronicDevice* newDevice;
public:
TurnTvOn(ElectronicDevice* device) {
newDevice = device;
}
void execute() {
newDevice->on();
}
};
class VolumnUp : public Command {
private:
ElectronicDevice* newDevice;
public:
VolumnUp(ElectronicDevice* device) {
newDevice = device;
}
void execute() {
newDevice->volumnUp();
}
};
// this is the invoker.
class DeviceButton {
private:
Command* theCommand;
public:
DeviceButton(Command* newCommand) {
theCommand = newCommand;
}
void press() {
theCommand->execute();
}
};
// this is the receiver
class Television : public ElectronicDevice {
private:
int volumn;
public:
Television(int v) : volumn(v) {}
void on() {
cout << "TV is ON" << endl;
}
void off() {
cout << "TV is OFF" << endl;
}
void volumnUp() {
volumn++;
cout << "volumn is at: " << volumn << endl;
}
void volumnDown() {
volumn--;
cout << "volumn is at: " << volumn << endl;
}
};
//test
int main(void) {
int volumn = 0;
ElectronicDevice* device = new Television(volumn);
TurnTvOn* onCommand = new TurnTvOn(device);
DeviceButton* onPressed = new DeviceButton(onCommand);
onPressed->press();
VolumnUp* volumnCommand = new VolumnUp(device);
onPressed = new DeviceButton(volumnCommand);
onPressed->press();
}