Wzorzec projektowy polecenie - command

Autor podstrony: Krzysztof Zajączkowski

Stronę tą wyświetlono już: 3888 razy

Opis wzorca projektowego polecenie

Wzorzec projektowy polecenie należy do czynnościowych wzorców projektowych. Jego celem jest umieszczenie w jednej klasie zarządzającej wszystkich poleceń, które mogą być wywołane np. przy wciśnięciu przycisku klawiatury. W tejże klasie przechowywane są interfejsy obiektów klas, które wykonują określone polecenie.

Przykład diagramu UML wzorca projektowego polecenie

Na poniższym diagramie UML klasa KeyboardCommands zawiera pole commands, które jest zdolne do przechowywania pary danych: klucz (char) → polecenie (iCommand). Klucz określa jednocześnie pod jaki przycisk klawiatury podpięty został dany interfejs polecenia.

Interfejs iCommand jest dziedziczony przez klasy, będące jednocześnie poleceniami programu. Są to klasy:

Pierwsze cztery klasy przechowują wskaźnik do obiektu klasy Car wywołując jego metody wewnętrzne odpowiedzialne za przemieszczanie się samochodu.

Przykładowy diagram UML dla wzorca projektowego polecenie
Rys. 1
Przykładowy diagram UML dla wzorca projektowego polecenie

Przykładowa implementacja wzorca projektowego polecenie w C++

#include <iostream> #include <string> #include <map> class Car{ int x; int y; public: Car(const int x, const int y): x(x), y(y){}; void moveLeft(){ x--; std::cout<<"Moved left" << std::endl; }; void moveRight(){ x++; std::cout<<"Moved right" << std::endl; }; void moveForward(){ y++; std::cout<<"Moved forward" << std::endl; }; void moveBack(){ y--; std::cout<<"Moved back" << std::endl; }; void writePos(){ std::cout<<"x "<<x<<" y "<<y<<std::endl; }; }; class iCommand{ protected: std::string commandName; public: iCommand(std::string commandName): commandName(commandName){}; virtual void doCommand() = 0; inline std::string getCommand(){return commandName;}; }; class CommandLeft : public iCommand{ Car *car; public: CommandLeft(Car *car):iCommand("Turn left"), car(car){}; virtual void doCommand(){ if(car != NULL){ car->moveLeft(); } } }; class CommandRight : public iCommand{ Car *car; public: CommandRight(Car *car):iCommand("Turn right"), car(car){}; virtual void doCommand(){ if(car != NULL){ car->moveRight(); } } }; class CommandForward : public iCommand{ Car *car; public: CommandForward(Car *car):iCommand("Move forward"), car(car){}; virtual void doCommand(){ if(car != NULL){ car->moveForward(); } } }; class CommandBack : public iCommand{ Car *car; public: CommandBack(Car *car):iCommand("Move back"), car(car){}; virtual void doCommand(){ if(car != NULL){ car->moveBack(); } } }; class CommandExit : public iCommand{ public: CommandExit():iCommand("Exit"){}; virtual void doCommand(){ std::cout<<this->getCommand()<<std::endl; } }; class KeyboardCommands{ std::map<char, iCommand*> commands; public: bool addCommand(char key, iCommand* ic){ if(commands.find(key) == commands.end()){ commands[key] = ic; return true; } return false; }; void writeCommandsList(){ for(std::map<char, iCommand*>::iterator i = commands.begin(); i != commands.end(); i++){ std::cout << i->second->getCommand() << " ["<<i->first<<"]" << std::endl; } } bool doCommand(char key){ if(commands.find(key) != commands.end()){ commands[key]->doCommand(); return true; } return false; } bool changeCommandKey(const char newKey, char &oldKey){ if(commands.find(newKey) == commands.end()){ commands[newKey] = commands[oldKey]; commands.erase(oldKey); oldKey = newKey; return true; } return false; } ~KeyboardCommands(){ for(std::map<char, iCommand*>::iterator i = commands.begin(); i != commands.end(); i++){ if(i->second != NULL){ delete i->second; i->second = NULL; } } } }; int main(){ std::map<char, iCommand*> commands; Car *car = new Car(10,10); KeyboardCommands keyboardGameMode; char exitKey = 'e'; keyboardGameMode.addCommand('a', new CommandLeft(car)); keyboardGameMode.addCommand('d', new CommandRight(car)); keyboardGameMode.addCommand('w', new CommandForward(car)); keyboardGameMode.addCommand('s', new CommandBack(car)); keyboardGameMode.addCommand(exitKey, new CommandExit()); KeyboardCommands *keyboard = &keyboardGameMode; car->writePos(); char key = 'w'; if(keyboard->changeCommandKey('x',exitKey)){ std::cout<<"Changed" << std::endl << std::endl; } do{ std::cout<<"Live or die, make your move:" << std::endl; keyboard->writeCommandsList(); std::cin>>key; if(keyboard->doCommand(key)){ car->writePos(); } }while(key != exitKey); if(car){ delete car; car = NULL; } std::cin.ignore(1); std::cin.get(); return 0; }

Przykładowy wynik działania programu:

x 10 y 10
Changed

Live or die, make your move:
Turn left [a]
Turn right [d]
Move back [s]
Move forward [w]
Exit [x]
a
Moved left
x 9 y 10
Live or die, make your move:
Turn left [a]
Turn right [d]
Move back [s]
Move forward [w]
Exit [x]
d
Moved right
x 10 y 10
Live or die, make your move:
Turn left [a]
Turn right [d]
Move back [s]
Move forward [w]
Exit [x]
w
Moved forward
x 10 y 11
Live or die, make your move:
Turn left [a]
Turn right [d]
Move back [s]
Move forward [w]
Exit [x]
s
Moved back
x 10 y 10
Live or die, make your move:
Turn left [a]
Turn right [d]
Move back [s]
Move forward [w]
Exit [x]
x
Exit
x 10 y 10
Strony powiązane
strony powiązane
  1. sourcemaking.com/design_patterns/command - strona opisująca wzorzec projektowy polecenie [En]
  2. pl.wikipedia.org - opis tego wzorca na stronie Wikipedii
Propozycje książek
tytuł: C++. Projektowanie oprogramowania. Zasady i wzorce projektowe autor: Klaus Iglberger

Tytuł:

C++. Projektowanie oprogramowania. Zasady i wzorce projektowe

Autor:

Klaus Iglberger

tytuł: Wzorce projektowe. Rusz głową! Tworzenie rozszerzalnego i łatwego w utrzymaniu oprogramowania obiektowego. Wydanie II autor: Eric Freeman, Elisabeth Robson

Tytuł:

Wzorce projektowe. Rusz głową! Tworzenie rozszerzalnego i łatwego w utrzymaniu oprogramowania obiektowego. Wydanie II

Autor:

Eric Freeman, Elisabeth Robson

tytuł: React 17. Wzorce projektowe i najlepsze praktyki. Projektowanie i rozwijanie nowoczesnych aplikacji internetowych. Wydanie III autor: Carlos Santana Roldán

Tytuł:

React 17. Wzorce projektowe i najlepsze praktyki. Projektowanie i rozwijanie nowoczesnych aplikacji internetowych. Wydanie III

Autor:

Carlos Santana Roldán

tytuł: Wzorce projektowe. Rusz głową! Tworzenie rozszerzalnego i łatwego w utrzymaniu oprogramowania obiektowego. Wydanie II autor: Eric Freeman, Elisabeth Robson

Tytuł:

Wzorce projektowe. Rusz głową! Tworzenie rozszerzalnego i łatwego w utrzymaniu oprogramowania obiektowego. Wydanie II

Autor:

Eric Freeman, Elisabeth Robson

tytuł: Wzorce projektowe w .NET Core 3. Projektowanie zorientowane obiektowo z wykorzystaniem C# i F# autor: Dmitri Nesteruk

Tytuł:

Wzorce projektowe w .NET Core 3. Projektowanie zorientowane obiektowo z wykorzystaniem C# i F#

Autor:

Dmitri Nesteruk

tytuł: Wzorce projektowe. Elementy oprogramowania obiektowego wielokrotnego użytku autor: Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides

Tytuł:

Wzorce projektowe. Elementy oprogramowania obiektowego wielokrotnego użytku

Autor:

Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides

tytuł: Projektowanie interfejsów., Sprawdzone wzorce projektowe. Wydanie III autor: Jenifer Tidwell, Charles Brewer, Aynne Valencia-Brooks

Tytuł:

Projektowanie interfejsów., Sprawdzone wzorce projektowe. Wydanie III

Autor:

Jenifer Tidwell, Charles Brewer, Aynne Valencia-Brooks

tytuł: Kubernetes. Wzorce projektowe. Komponenty wielokrotnego użycia do projektowania natywnych aplikacji chmurowych autor: Bilgin Ibryam,  Roland Huß

Tytuł:

Kubernetes. Wzorce projektowe. Komponenty wielokrotnego użycia do projektowania natywnych aplikacji chmurowych

Autor:

Bilgin Ibryam, Roland Huß

tytuł: Wzorce projektowe w .NET. Projektowanie zorientowane obiektowo z wykorzystaniem C# i F# autor: Dmitri Nesteruk

Tytuł:

Wzorce projektowe w .NET. Projektowanie zorientowane obiektowo z wykorzystaniem C# i F#

Autor:

Dmitri Nesteruk

tytuł: Programowanie zorientowane obiektowo. Wzorce projektowe. Wydanie II autor: Alan Shalloway, James R. Trott

Tytuł:

Programowanie zorientowane obiektowo. Wzorce projektowe. Wydanie II

Autor:

Alan Shalloway, James R. Trott

W związku z tym, że firma Helion nie wywiązuje się z swoich zobowiązań naliczania prowizji za każdą zakupioną książkę a kontakt z ową frmą jest nie możliwy autor strony zmuszony został do zablokowania linkowania książek. Za wszelkie niedogodności z tym związane z góry przepraszam i obiecuję włączenie linkowania gdy tylko sprawa zostanie wyjaśniona