Zastosowanie
Dekorator
(ang. Decorator
) (wzorzec strukturalny) umożliwia rozszerzenie funkcjonalności lub modyfikacje stanu istniejącego obiektu bez zmiany jego struktury w trakcie działania programu. Jest alternatywą dla dziedziczenia
, które w przeciwieństwie do Dekoratora
zachodzi w trakcie kompilacji. Wzorzec ten jest swego rodzaju Wrapperem
dla istniejącej klasy. Obiekt klasy podstawowej może być rozszerzony przez kilka dekoratorów umożliwiając tym samym tworzenie wielu wariantów zachowań bez ingerencji w strukturę rozszerzanej klasy. Proces ten odnosi się do jednego obiektu, a nie wszystkich instancji klasy. Dzięki temu struktura klas oraz dziedziczenia staje się przejrzysta, a projekt jest otwarty i elastyczny na przyszłe modyfikacje i nowe rozszerzenia.
Ograniczenia
Zagrożenie płynące ze stosowania Dekoratora
może być nadmiarowa ilość małych klas. Należałoby wówczas zastanowić się czy implementacja tego wzorca jest rzeczywiście najlepszym sposobem rozwiązania problemu. Dekorator jest trudny w zastosowaniu dla wielokrotnie
Użycie
Dekorator
bywa często używany w implementacji kontrolek interfejsu - klas View
. Można go spotkać w strumieniach I/O w Javie
. Jest on implementowany tam, gdzie zachodzi potrzeba tworzenia wielu zachowań dla obiektów tego samego typu w zależności od miejsca ich wystąpienia, a użycie dziedziczenia jest zbyt kosztowne lub nie możliwe do przewidzenia. Takim przykładem może być proces składanie zamówienia danego produktu z opcją dodania do niego składników. Używając Dekoratora
dla 5 rozszerzeń wystarczy utworzyć 5 Dekoratorów. Korzystając z dziedziczenia
, aby zachować tą samą ilość typów należałoby stworzyć aż 31 klas!
Implementacja
Podstawowe klasy komponentów Component1
, Component2
itd. oraz klasa bazowa dekoratora Decorator
rozszerzają klasę abstrakcyjną lub implementują wspólny interfejs Component
. Decorator
przyjmuje jako parametr obiekt klasy Component
. Klasy dekoratorów Decorator1
, Decorator2
itd. rozszerzają bazową klasę Decorator
. Dekoratory implementują nowe funkcję oraz rozszerzają działanie metod klasy bazowej Component
.
Poniższe listing przedstawiają przykładową implementacje wzorca Dekorator
.
Tak zaimplementowany wzorzec można wykorzystać w następujący sposób.
Przykład
Aplikacja jest szkicem procesu budowania awatara (Component
) postaci w grze komputerowej. Gracz rozwija swoją postać na różnych etapach gry poprzez zdobywanie punktów siły oraz nowych umiejętności (Decorator
). Interakcje między postaciami jak np.: walka zależą od siły ich profili. Profil ten zmienia się w czasie, a dzięki różnorodności zdobywanych umiejętności świat postaci jest różnorodny. Poniższy listing przedstawia podstawowe komponenty wzorca.
Postać w grzę zyskuje dodatkowe punkty siły, moce, a także zmienia sposób walki za pomocą następujących dekoratorów (profili).
Schemat zdobywania nowych umiejętności oraz interakcji między postaciami (rozłożony w czasie) mógłby wyglądać jak na poniższym listingu.
Biblioteki
Z uwagi na prostote wzorca, jego specyfikę i niski koszt implementacji używanie bibliotek implementujących wzorzec Dekorator
mija się z celem. Najczęstszym jego wykorzystaniem w Androidzie
jest rozszerzanie widoków. Decor
jest przykładem biblioteki, która ułatwia dodawanie dekoratorów do klas View
. Przykładem implementacji wzorca w Javie
są wszystkie podklasy InputStream
, OutputStream
, Reader
czy też Writer
.