Polecenie (ang. Command, komenda) – czynnościowy wzorzec projektowy, traktujący żądanie wykonania określonej czynności jako obiekt, dzięki czemu mogą być one parametryzowane w zależności od rodzaju odbiorcy, a także umieszczane w kolejkach i dziennikach.
Problem
Rozpatrzmy typową aplikację okienkową realizującą jakieś zadanie. Użytkownik może wykonać w niej różne czynności. Chcemy umożliwić mu cofanie zmian oraz przeglądanie ich historii, dlatego niezbędny jest nam mechanizm, który oprócz obsługi żądań, będzie je także zapamiętywał na stosie.
Budowa
Wzorzec Polecenie zakłada utworzenie oddzielnej klasy dla każdego zadania implementującej pewien wspólny interfejs Polecenie
. Mamy także stronę generującą zadania do wykonania (nadawca), którą może być kod obsługi zdarzeń myszki i klawiatury, a także jeden lub więcej obiektów odpowiedzialnych za obsługę poleceń (odbiorca). Aby wykonać operację, nadawca tworzy obiekt określonego zadania i przekazuje go do wybranego odbiorcy, który odpowiada za wywołanie metody wykonaj()
.
Dopuszczalne jest parametryzowanie polecenia przed jego wykonaniem, zarówno po stronie odbiorcy, jak i nadawcy. Dodatkowo, odbiorca może zapamiętać obiekt polecenia na stosie, oferując programowi usługę wycofywania operacji lub przeglądania historii. Wspólny interfejs Polecenie
musi być wtedy rozszerzony o dodatkowe metody takie, jak ustawParametr()
czy wycofaj()
.
Wykaz elementów składowych wzorca:
- polecenie — interfejs definiujący operacje, jakie musi obsługiwać każde polecenie (wykonywanie zadania, wycofywanie zmian itd.)
- konkretne polecenie — klasa dostarczająca implementacji interfejsu polecenia, koncentrująca się na obsłudze pojedynczego zadania. Dla każdego rodzaju obsługiwanego polecenia tworzymy oddzielną klasę.
- model — dowolny obiekt, na którym polecenia potrafią wykonać operacje. W praktyce w skład modelu może wchodzić dowolnie duża liczba klas i obiektów.
- nadawca — dowolny obiekt, który potrafi generować obiekty poleceń.
- odbiorca — obiekt wykonujący polecenia poprzez wywołanie metody
wykonaj()
na przekazanym do niego obiekcie. Oprócz tego, może wykonać dodatkowe operacje związane z jego obsługą (np. zapisanie polecenia w dzienniku lub historii zmian).
Konsekwencje użycia
Zalety:
- oddzielenie operacji od obiektów, na których jest ona wykonywana,
- polecenia są reprezentowane jako standardowe obiekty, dzięki czemu możemy na nich stosować wszystkie manipulacje dopuszczalne w programowaniu obiektowym,
- możliwość łączenia elementarnych poleceń w polecenia złożone,
- łatwość dodawania nowych rodzajów poleceń.
Wady:
- każde polecenie wymaga dodatkowej pamięci na zapamiętanie stanu swojego obiektu.
Implementacja
Implementacja wzorca wymaga przeanalizowania następujących kwestii:
- stopień skomplikowania polecenia — jak dużą odpowiedzialność powinny mieć polecenia? Czy będą to jedynie proste obiekty wykonujące operację na dostarczonym modelu czy też złożone implementacje, które nie delegują do odbiorcy żadnych zadań?
- czy będziemy obsługiwać wycofywanie operacji — oprócz dodania do interfejsu metody
wycofaj()
, polecenia muszą również zapamiętywać wystarczająco dużo informacji o stanie, aby umożliwić jego odtworzenie. Wszystkie operacje, jakie wykonujemy na modelu, muszą być wycofywalne i należy dla każdej z nich zaimplementować odpowiednią klasę polecenia. W przeciwnym wypadku wielokrotne wykonywanie i wycofywanie poleceń może doprowadzić do nawarstwiania się błędów oraz utraty bądź uszkodzenia danych. Do zapamiętywania stanu obiektu sprzed wykonania operacji bez ujawniania szczegółów jego wewnętrznej struktury można wykorzystać wzorzec Pamiątka.
Zastosowanie
Wzorzec znajduje zastosowanie wszędzie tam, gdzie musimy zapamiętywać wykonywane operacje lub je wycofywać. Mogą to być zarówno przedstawione wyżej programy okienkowe z opcją cofania, jak i np. systemy obsługi transakcji w instalatorach lub bazach danych i mechanizmy nagrywania makr. Drugim obszarem zastosowań są sytuacje, gdy identyczne polecenia muszą być parametryzowane różnymi danymi w zależności od tego, kto odpowiada za ich obsłużenie.
Wzorzec Polecenie znalazł też zastosowanie w implementacjach mechanizmów zdalnego wykonywania procedur, gdzie obiekty żądań są serializowane i przesyłane jako strumień bajtów do innego komputera, który odpowiada za ich wykonanie.
Zobacz też
Bibliografia
- Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides: Wzorce projektowe. Elementy oprogramowania obiektowego wielokrotnego użytku. Helion, 2010, s. 302-311. ISBN 978-83-246-2662-5.