Kurs AngularJS #14 – Dekoratory

Dekoratory to tak naprawdę wzorzec projektowy używany w celu oddzielenia rzeczywistych modyfikacji od “dekoracji” a więc jakiegoś rozszerzenia funkcjonalności bez zmiany oryginalnego kodu źródłowego. W Angularze dekoratorami są funkcje które umożlwiają zmodyfikowanie serwisów, dyrektyw i filtrów przed ich użyciem.

Dekoratorów możemy używać na dwa sposoby: poprzez $provider.decorator lub module.decorator. Obydwa dają dostęp do $delegate, która jest instancją danego serwisu, dyrektywy bądź filtra jeszcze przez jego użyciem kiedy jest to wymagane.

$provide.decorator

Funkcja dekoratora pozwala na dostęp do $delegate konkretnej usługi zaraz po tym jak zostanie stworzona jej instancja. Zerknijmy na jakiś przykład.

Dekorator jest odpalany zaraz po stworzeniu instancji serwisu $log. Funkcja dekoratora ma podany w zależnościach obiekt $delegate żeby uzyskać dostęp do serwisu podanego w dekoratorze. Tak naprawdę to $delegate będzie tym serwisem który będziemy dekorować. Wartość którą zwróci funkcja dostarczona do dekoratora zajmie miejsce serwisu, dyrektywy bądź filtra który jest dekorowany.

$delegate może być zmodyfikowany lub nawet całkowicie zastąpiony poprzez wartość którą podajemy.

Możemy również dokonać aktualizacji czegoś.

Lub poszerzyć zakres funkcjonalności.

Dekoratory kierują się trochę innymi zasadami dla różnych usług. Dzieje się tak dlatego, że same te usługi są rejestrowane w różny sposób. Serwisy są wybierane po nazwie, jednakże filtry i dyrektywy wymagają dodania do ich nazw odpowiednio “Filter” i “Directive”. Ponadto o ile w serwisach $delegate jest funkcją bądź obiektem zwracanym przez ten serwis to w przypadku dyrektyw jest to Array.<DirectiveObject> a w przypadku filtra funkcja.

module.decorator

Ta funkcja jest praktycznie dokładnie taka sama jak $provide.decorator z tą różnicą, że jest dostępna poprzez zewnętrzne API modułu i umożliwia odseparowanie wzorca dekoratora od bloku konfiguracyjnego modułu. Tak samo jak w przypadku $provide.decoratormodule.decorator uruchamiana jest podczas fazy konfiguracyjnej naszej aplikacji. Oznacza to że definiujemy ją jeszcze zanim serwis który dekorujemy zostanie zdefiniowany.

Wartym zauważenia jest też fakt, że dekorowanie aplikacji przebiega w określonym porządku:

  • Jeśli usługa dekorowana jest zarówno przez $provide.decorator jak i przez module.decorator są one stosowane w takiej kolejności:
  • Jeśli usługa jest deklarowana wiele razy, dekorator ozdobi tą która została zadeklarowana ostatnia:

Przykładowe aplikacje

Postaram Ci się teraz pokazać przykłady udekorowania zarówno serwisów, dyrektyw jak i filtrów na osobnych przykładach i objaśnić wszystko co może się w nich wydać niejasne tak, żebyś w pełni zrozumiał ten temat.

Serwis

Zajmiemy się udekorowaniem serwisu $log o to jak wyświetlane są wiadomości.

Jest to dosyć długi kod a jego analizę rozpoczniemy od bloku konfiguracyjnego gdzie rzeczywiście dzieje się to co w tej części powinno nas interesować. Na początku mamy zdefiniowany obiekt który zawiera w sobie właściwości reprezentujące typy logów które chcemy widzieć. Każda z tych właściwości ma przypisaną funkcję której argumentem jest rzeczywista wiadomość a wywołuje ona funkcję log zdefiniowaną poniżej podając jej jako pierwszy argument tą wiadomość a jako drugi – typ. W tym obiekcie mamy również tablicę stack.

Funkcja log dodaje do tablicy stack obiektu myLog obiekt który ma dwie właściwości: typ i wiadomość. Następnie odpalane jest polecenie consol z wybranym typem i wiadomością. Tak zmodyfikowany serwis $log jest zwracany.

Przejdźmy teraz do kontrolera. Posiada on tablicę ze wszystkimi dostępnymi po naszej dekoracji typami logów. Następnie iteruje przez nią wyświetlając komunikat każdego możliwego rodzaju. Dodatkowo $log zostaje użyte w $timeout.

Sama dyrektywa działa bardzo podobnie przy czym pokazuje ona nam nasze komunikaty w dokumencie. Różnią się one od siebie dzięki zdefiniowaniu odpowiednich stylów.

Samo użycie dyrektywy w kodzie HTML naszej strony wygląda następująco:

Dyrektywa

Mam nadzieję, że komentarze w kodzie są wystarczającym wytłumaczeniem tych być może niezrozumiałych kwestii.

Dzięki temu możemy natomiast przetestować nasze dekoracje.

Filtr

Załóżmy, że stworzyliśmy filtr który używa standardowego formatowania dla naszych dat. Niestety jednak wymagania uległy zmianie i potrzebujemy mieć wszystkie nasze domyślne daty w formacie shortDate zamiast mediumDate.