Command design pattern
#include iostream
#include <vector>
#include <map>
#include <string>
#include <memory>
using std::cout;
using std::cin;
using std::endl;
using std::string;
using std::vector;
using std::pair;
using std::unique_ptr;
//------
//Implementing menus - non object oriented design
class Menu {
public:
void activate() {
int n;
do {
show();
n = getOptionFromUser();
} while (performAction(n));
}
private:
enum {OPEN,SAVE,EXIT};
void show() {
cout < OPEN < "- open\n";
cout < SAVE < "- save\n";
cout < EXIT < "- exit\n";
}
int getOptionFromUser() {
cout < "your choice: ";
int n;
cin>n;
return n;
}
bool performAction(int n) {
switch(n) {
case OPEN:
cout < "Opening a file ...\n";
break;
case SAVE:
cout < "Saving a file ...\n";
break;
case EXIT:
return false;
}
return true;
}
};
int main() {
Menu m;
m.activate();
}
//------
//Implementing menus - object oriented design
class Command {
public:
virtual void execute() = 0;
};
class Menu {
public:
void add(string name, unique_ptrCommand> c) {
m_options.emplace_back(option(name, move(c)));
}
void activate() {
int n;
do {
show();
n = getOptionFromUser();
} while (performAction(n));
}
~Menu() {}
private:
typedef pairstring, unique_ptrCommand> option;
vectoroption> m_options;
void show() {
for (unsigned i = 0; im_options.size(); i++)
cout i " - " m_options[i].first " \n";
cout m_options.size() "- Exit\n";
}
int getOptionFromUser() {
cout "your choice: ";
int n;
cin n;
return n;
}
bool performAction(unsigned n) {
if (n >= m_options.size())
return false;
m_options[n].second->execute();
return true;
}
};
class Open : public Command {
public:
virtual void execute() {
cout "Opening a file ...\n";
}
};
class Save : public Command {
public:
virtual void execute() {
cout "saving a file ...\n";
}
};
int main() {
Menu m;
m.add("Open", std::make_uniqueOpen>());
m.add("Save", std::make_uniqueSave>());
m.activate();
}
//------
//Adding submenus
class SaveAs : public Command {
public:
virtual void execute() {
cout "saving a file as ...\n";
}
};
class SaveAll : public Command {
public:
virtual void execute() {
cout "saving all files ...\n";
}
};
class Save : public Command {
public:
virtual void execute() {
cout "saving a file ...\n";
Menu m; //Sub menu
m.add("Save as", std::make_uniqueSaveAs>());
m.add("Save all", std::make_uniqueSaveAll>());
m.activate();
}
};
//------
//Implementing menus using function pointers - less object oriented design
//Differences marked with "*"
class Menu {
public:
void add(string name, void(*c)()) { //*
m_options.emplace_back(option(name, c));
}
void activate() {
int n;
do {
show();
n = getOptionFromUser();
} while (performAction(n));
}
private:
typedef pairstring, void(*)()> option; //*
vectoroption> m_options;
void show() {
for (unsigned i = 0; im_options.size(); i++)
cout i " - " m_options[i].first " \n";
cout m_options.size() "- Exit\n";
}
int getOptionFromUser() {
cout "your choice: ";
int n;
cin n;
return n;
}
bool performAction(unsigned n) {
if (n >= m_options.size())
return false;
(m_options[n].second)(); //*
return true;
}
};
//*
void executeOpen() {
cout "Opening a file ...\n";
}
//*
void executeSave() {
cout "saving a file ...\n";
}
int main() {
Menu m;
m.add("Open", executeOpen); //*
m.add("Save", executeSave); //*
m.activate();
}
//------
//Implementing menus - more object oriented design advantages
class Command {
public:
virtual void execute() = 0;
};
class Menu {
public:
void add(string name, unique_ptrCommand> c) {
m_options.emplace_back(option(name, move(c)));
}
void activate() {
int n;
do {
show();
n = getOptionFromUser();
} while (performAction(n));
}
~Menu() {}
private:
typedef pairstring, unique_ptrCommand> option;
vectoroption> m_options;
void show() {
for (unsigned i = 0; im_options.size(); i++)
cout i " - " m_options[i].first " \n";
cout m_options.size() "- Exit\n";
}
int getOptionFromUser() {
cout "your choice: ";
int n;
cin n;
return n;
}
bool performAction(unsigned n) {
if (n >= m_options.size())
return false;
m_options[n].second->execute();
return true;
}
};
class Rotate : public Command {
public:
Rotate(double angle = 0.0) : m_angle(angle) {}
virtual void execute() {
cout "Rotating a shape according to angle: " m_angle endl;
}
private:
double m_angle;
};
class Trnaslate : public Command {
public:
Trnaslate(double transX = 0.0, double transY = 0.0) : m_transX(transX), m_transY(transY) {}
virtual void execute() {
cout "Trnaslating a shape according to (" m_transX "," m_transY ")" endl;
}
private:
double m_transX, m_transY;
};
class Delete : public Command {
public:
Delete(unsigned index = 0) : m_index(index) {}
virtual void execute() {
unsigned index;
cout "choose a shape to delete: ";
cin index;
cout "Deleting shape number: " index endl;
}
private:
unsigned m_index;
};
int main() {
Menu m;
m.add("Rotate", std::make_uniqueRotate>(90.0));
m.add("Trnaslate", std::make_uniqueTrnaslate>(2.0, 3.0));
m.add("Delete", std::make_uniqueDelete>());
m.activate();
}