Wzorce projektowe – Polecenie

 wrz, 12 - 2020   PHPWzorce Projektowe

Polecenie, inaczej nazywany komendą (command), należy do rodziny czynnościowych wzorców projektowych, którego zadaniem jest agregacja i hermetyzacja żądań do wykonania. Żądania te traktowane są jako osobne obiekty, które mogą być parametryzowane w zależności od rodzaju odbiorcy.

 

 

 

 

Charakterystyka wzorca polecenie

 

Poniżej przedstawiony jest diagram UML, pokazujący strukturę wzorca.

 

Diagram UML - Wzorzec Projektowy Polecenie

Patrząc na diagram UML wzorca polecenia, możemy wyróżnić kilka elementów:

  • polecenie – interfejs definiujący metody jakie każde konkretne polecenie musi wykonać, zazwyczaj są to metody typu wykonaj (execute), cofnij (undo), ustaw parametr (setParameter), itp.
  • konkretne polecenie – klasa, implementująca interfejs polecenia; dla poszczególnych komend definiujemy osobną klasę
  • odbiorca (receiver) – jest przedmiotem akcji wykonywanej przez polecenie, komunikuje się z konkretnym poleceniem, przekazując żądania klienta
  • nadawca (invoker) – ustala odbiorcę żądania, wywołuje metody polecenia
  • klient (client) – nasza aplikacja, tworzy konkretne polecenie, ustawia odbiorcę i używa nadawcę

 

 

 

Przykład zastosowania wzorca polecenie – obsługa urządzenia elektronicznego

 

Teoria może wyglądać dosyć skomplikowanie, dlatego najłatwiej zrozumieć działanie tego wzorca na konkretnym przykładzie. Przykładowa aplikacja będzie miała zadanie utworzenie urządzenia elektronicznego(np. telewizora lub radia), a następnie utworzenie i wykorzystanie poleceń sterujących tymi odbiornikami.

W przełożeniu na powyższy diagram i jego opis:

  • poleceniami będą: włącz (turn on), wyłącz (turn off), pogłośnij (turn volume up), ścisz (turn volume down)
  • odbiorcą będzie telewizor lub radio
  • nadawcą będzie pilot (remote controller)

Zaczynamy od utworzenia interfejsu dla naszych urządzeń elektrycznych, który deklaruje akcje wykonywane przez konkretne urządzania, tj. włączanie, wyłącznie urządzania lub zmiana głośności.

Dalej piszemy klasy konkretnych urządzeń implementujące interfejs.

Kolejnym elementem będzie utworzenie poleceń wywoływanych na rzecz odbiorcy, czyli klasy telewizora. Zacznijmy od interfejsu polecenia.

Jak widzimy, nasze polecenia oprócz metody execute (wykonaj), będzie również mogły cofać wykonanie polecenia za pomocą metody undo.

Tworzymy klasy dla poszczególnych poleceń. Polecenie w konstruktorze będzie otrzymywał obiekt odbiorcy (czyli w tym przypadku urządzenie elektryczne) na rzecz którego polecenie będzie wykonywane.

Ostatnim elementem jest nadawca (w naszej aplikacji będzie to pilot – remote controller), którego zadaniem będzie wykonywanie przekazanych poleceń.

Teraz łączymy wszystko w naszej aplikacji.

W pierwszej kolejności aplikacja (klient) tworzy konkretne urządzenie elektryczne, a następnie definiuje polecenia, które chcemy wykonać. Następnie tworzona jest instancja pilota, która  steruje wykonywaniem poszczególnych poleceń na rzecz urządzenia.

Wynikiem działania aplikacji jest:

 

Powyższy przykład można zobaczyć i pobrać na GitHub: https://github.com/molitorys/design-patterns/tree/master/src/Command/ElectronicDevice

 

 

Podsumowanie

 

Na pierwszy rzut oka, zastosowanie wzorca polecenia może wydawać się niepotrzebną komplikacją. I faktycznie, wzorzec ten wymusza tworzenie wielu obiektów i wprowadza kilka nowych elementów, które mogą wydawać się zbędne. Osobiście, dla mniejszych projektów nie zawracałbym sobie specjalnie głowy tym wzorcem, natomiast dla większych projektów może być bardzo pomocny. Zastosowanie poleceń pozwala na:

  • hermetyzacje żądań,
  • umożliwia oddzielenie kodu wysyłania (invoker) i odbierania (receiver) żądań,
  • pozwala na monitorowanie wykonywania żądań,
  • pozwala na cofanie poleceń,
  • umożliwia manipulowanie poleceniami i łatwe dodawanie nowych,
  • daje nam bardziej elastyczny i ładniejszy kod.

Przeczytaj równierz