Dekorátor je jeden ze strukturálních návrhových vzorů, které řeší otázku struktury programu. Je znám také pod názvem Wrapper.
Dekorátor se vytváří za účelem změny instancí tříd bez nutnosti vytvoření nových odvozených tříd, jelikož pouze dynamicky připojuje další funkčnosti k objektu. Každá dodaná funkčnost je u dekorátoru implementována jako „ozdobení“ (dekorování) jiného objektu. Dekorátor tedy rozšiřuje objekt, ne třídu, jak je tomu u statické dědičnosti.
Problematika dekorátoru bude uvedena na velmi jednoduchém příkladu, aby došlo k rychlému osvojení. Je zapotřebí vytvořit zmrzlinu a k ní několik odlišných polev, které zmrzlinu ozdobí. Pokud bude použit návrhový vzor dekorátor, je zapotřebí si nadefinovat základní zmrzlinu a poté si nadefinovat polevy, kterými bude zmrzlina ozdobena, viz obrázek - UML diagram. Příklad je uveden v jazyce Java, ale k pochopení základního principu postačí znalost kteréhokoliv objektově orientovaného jazyka.
public interface Icecream {
public String makeIcecream();
}
public class SimpleIcecream implements Icecream {
@Override
public String makeIcecream() {
return "Base Icecream";
}
}
abstract class IcecreamDecorator implements Icecream {
protected Icecream specialIcecream;
public IcecreamDecorator(Icecream specialIcecream) {
this.specialIcecream = specialIcecream;
}
public String makeIcecream() {
return specialIcecream.makeIcecream();
}
}
public class HoneyDecorator extends IcecreamDecorator {
public HoneyDecorator(Icecream specialIcecream) {
super(specialIcecream);
}
public String makeIcecream() {
return specialIcecream.makeIcecream() + addHoney();
}
private String addHoney() {
return " + sweet honey";
}
}
public class NuttyDecorator extends IcecreamDecorator {
public NuttyDecorator(Icecream specialIcecream) {
super(specialIcecream);
}
public String makeIcecream() {
return specialIcecream.makeIcecream() + addNuts();
}
private String addNuts() {
return " + crunchy nuts";
}
}
Nyní lze použít kterékoliv dekorátory v kterémkoliv pořadí. Tato flexibilita a proměnlivost chování instance za běhu, jak si zvolíme, je základní výhoda návrhového vzoru dekorátor
public class TestDecorator {
public static void main(String args[]) {
Icecream icecream = new HoneyDecorator(new NuttyDecorator(new SimpleIcecream()));
System.out.println(icecream.makeIcecream());
}
}
Předešlá testovací třída vytvoří takovýto výstup
"Base Icecream + crunchy nuts + sweet honey"
Dekorátor je velmi podobný adaptéru, ale nepřekrývá původní protokol ošetřovaného objektu. Dekorátor je v určitých případech také vhodnější než obyčejné dědění, jelikož při vytvoření nové funkčnosti by v případě klasické dědičnosti zdědily tuto funkčnost všechny objekty a to znamená, že i ty, které by funkčnost vůbec nepotřebovaly. To se u dekorátoru nestane.