Command

Przeznaczenie

  • Hermetyzuje żądania w postaci obiektu

  • Umożliwia:

    • parametryzowanie klientów różnymi żądaniami

    • kolejkowanie żądań oraz zapisywanie w dziennikach

  • Ułatwia implementację anulowania operacji

  • Usuwa sprzężenie pomiędzy obiektem wystawiającym żądanie, a obiektem, który wie, jak należy je zrealizować

  • Hermetyzuje odbiorcę (obiekt realizujący) z operacją lub szeregiem operacji, które mają być zrealizowane

Kontekst/Problem

Chcemy w aplikacji:

  • Sparametryzować obiekty wykonywaną akcją – Command jest obiektowym zastępcą wywołania funkcji zwrotnych

  • Tworzyć polecenia typu makro

  • Uwzględnić możliwość anulowania wprowadzonych zmian

  • Umożliwić wpisywanie zmian do dziennika transakcji, tak by można je było ponownie wykonać, gdy dojdzie do awarii systemu

Struktura

_images/Command.png

Uczestnicy

Command – deklaruje interfejs do wykonywania operacji

ConcreteCommand

  • definiuje powiązanie między obiektem Receiver i akcją

  • implementuje operację Execute() przez wywołanie odpowiednich operacji odbiorcy

Client – tworzy obiekt ConcreteCommand i ustala jego odbiorcę

Invoker – prosi polecenie o spełnienie żądania

Receiver

  • wie, jak wykonać operacje związane ze spełnieniem żądania

  • odbiorcą może być dowolna klasa

Współpraca

  • Klient tworzy obiekt konkretnego polecenia (ConcreteCommand) i podaje jego odbiorcę

  • Obiekt wywołujący (Invoker) przechowuje obiekt ConcreteCommand

  • Invoker zgłasza żądanie, wywołując operację Execute() polecenia

  • Jeśli polecenie jest wycofywalne, to przed wywołaniem akcji ConcreteCommand zapamiętuje stan umożliwiający późniejsze wycofanie go

  • Obiekt ConcreteCommand wywołuje operację swojego odbiorcy w celu spełnienia żądania.

Konsekwencje

  1. Wzorzec Command oddziela obiekt, który wywołał operację, od tego, który wie, jak ją wykonać. Separacja interfejsów wywołującego od odbiorcy.

  2. Polecenia są obiektami. Mogą być przetwarzane i rozszerzane tak jak inne obiekty.

  3. Z poszczególnych poleceń można tworzyć polecenia złożone. Polecenia złożone są egzemplarzami wzorca Composite (kompozyt).

  4. Można łatwo dodawać nowe polecenia, gdyż nie wymaga to modyfikowania istniejących klas.

Implementacja

Polecenia mogą wspomagać anulowanie i przywracanie operacji, o ile zapewniają odpowiednie narzędzia do tego (np. operację Undo lub Redo). Klasa ConcreteCommand może wymagać w tym celu pamiętania dodatkowego stanu.

Stan ten może zawierać:

  • obiekt odbiorcy (Receiver), który faktycznie wykonuje operacje w odpowiedzi na żądanie

  • argumenty operacji wykonywanych przez odbiorcę

  • wszystkie początkowe wartości z odbiorcy, które mogą zmienić się w wyniku obsługi żądania – odbiorca musi zapewnić operacje, które umożliwiają przywrócenie odbiorcy do poprzedniego stanu

Wzorce pokrewne

  1. Composite – wzorzec ten może zostać użyty do implementacji poleceń typu makro.

  2. Prototype – polecenie, które musi być skopiowane przed umieszczeniem go na liście poleceń, działa jak Prototype (prototyp).

  3. Memento – wzorzec często wykorzystywany do implementacji anulowania operacji.

Podsumowanie

  1. Oddziela obiekt żądający wykonania danej operacji od obiektu, który wie jak tą operację wykonać.

  2. Ułatwia kolejkowanie, selekcję i sterowanie czasem wykonywania poleceń.

  3. Ułatwia wycofywanie i ponowne wykonywanie poleceń.

  4. Ułatwia utrzymywanie trwałej historii wykonanych poleceń.