Wzorzec Decorator jest wzorcem strukturalnym. Jego rolą jest nadawanie obiektowi nowych funkcjonalności ale jednocześnie zapobiec eksplozji klas, która mogłaby w takiej sytuacji wystąpić. Drugą zaletą dekoratorów jest to, że możemy zmieniać funkcjonalność dynamicznie w trakcie działania programu.
Dekoratory implementują ten sam interfejs co klasa, której funkcjonalność mają rozszerzyć i przyjmuja oryginalny obiekt jako parametr konstruktora. Wszystkie metody są delegowane do obiektu ‚wyżej’ i dodatkowo wykonywane nowe funkcjonalności.

Przykład:

Zaprojektujemy system deserów, gdzie każdy z deserów będzie mógł być przystrojony jakimś dodatkiem jak bita śmietana czy wisionka.

Najpierw budujemy interfejs Deser:

Teraz tworzymy jakis deser np. Lody Waniliowe:

Dekoratory powinny implementować ten sam interfejs co klasa oryginalna. Stwórzmy więc abstrakcyjna klasę dla wszystkich dekoratorów:

Teraz tworzymy dwa prawdziwe dekoratory:

Metody getName() dekoratorów najpierw delegują metodę do obiektu wyżej i dodają nową funkcjonalność w postaci nazwy dekoratora.
Sprawdźmy:

Wynik działania programu:
Lody waniliowe plus bita śmietana plus bita śmietana i wisionka

Diagram wzorca:


.