Wzorzec Dekorator
2 września, 2022 19:39 | by Agnieszka | Posted in Wzorce projektowe

Dekorator to strukturalny wzorzec projektowy pozwalający dodawać nowe obowiązki obiektom poprzez umieszczanie tych obiektów w specjalnych obiektach opakowujących, które zawierają odpowiednie zachowania.
Dekorator znany jest również pod nazwą “Nakładka” – to słowo dobrze wyraża główną ideę tego wzorca. Nakładka jest obiektem który może być połączony z jakimś docelowym obiektem, zawiera ten sam zestaw metod jak obiekt docelowy i deleguje mu wszelkie otrzymywane żądania.
Załóżmy, że chcemy zaimplementować różne rodzaje samochodów – możemy stworzyć interfejs Car, aby zdefiniować metodę konstruowania samochodu. Następnie możemy tworzyć różne rodzaje samochodów – standardowe, sportowe, luksusowe. Hierarchia będzie jak poniżej:
Ale co jeśli będziemy chcieć samochód, który ma zarówno cechy auta luksusowego jak i sportowego? Lub będziemy mieć znacznie więcej rodzajów aut. Do tego chcielibyśmy wskazać, które z cech mają zostać dodane jako pierwsze. Implementacja wykorzystująca dziedziczenie i kompozycję będzie trudna do zarządzania. W takiej sytuacji warto zastosować właśnie wzorzec dekorator.
Na początku tworzymy interfejs:
Naszą implementacją konkretnego komponentu będzie klasa BasicCar
Bazowy dekorator implementuje interfejs komponentu:
Konkretni Dekoratorzy definiują dodatkowe zachowania które można przypisać do komponentów dynamicznie. Konkretni dekoratorzy nadpisują metody dekoratora bazowego i wykonują swoje działania albo przed, albo po wywołaniu metody klasy-rodzica. Możemy mieć klasy LuxuryCar i SportsCar.
Program testowy:
Zastosowanie:
gdy chcemy przypisywać dodatkowe obowiązki obiektom w trakcie działania programu, bez psucia kodu, który z tych obiektów korzysta
gdy rozszerzenie zakresu obowiązków obiektu za pomocą dziedziczenia byłoby niepraktyczne lub niemożliwe
Zalety:
– można rozszerzać zachowanie obiektu bez tworzenia podklasy
– można dodawać lub usuwać obowiązku obiektu w trakcie działania programu
– możliwe jest łączenie wielu zachowań poprzez nałożenie wielu dekoratorów na obiekt
– zasada pojedynczej odpowiedzialności – można podzielić klasę monolityczną, która implementuje wiele wariantów zachowań na mniejsze klasy
Wady:
– zabranie jednej konkretnej nakładki ze środka stosu nakładek jest trudne
– trudno jest zaimplementować dekorator w taki sposób, aby jego zachowanie nie zależało od kolejności ułożenia nakładek na stosie
– bazuje na dziedziczeniu, a w javie klasy mogą dziedziczyć tylko po jednym rodzicu to wykorzystanie tego wzorca blokuje dziedziczenie po jakiś klasach potrzebnych z biznesowego punktu widzenia
– pomimo ograniczania ilości klas dekorujących, i tak tworzy się ich spora ilość