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();

}