Dekorator kojarzy nam się z upiększaniem danego przedmiotu. W programowaniu de facto pełni tę samą funkcję czyli upiększa obiekty a także uszczegóławia je, czyni opis bardziej dokładnym co z kolei pozwala na lepsze odzwierciedlenie ich w naszym programie. Można to uczynić w sposób dynamiczny poprzez przypisywanie rozszerzeń danej klasie. Aby zrozumieć ten problem rozpatrzmy Problem Pizzerii

Na początku przyjrzyjmy się klasie abstrakcyjnej Pizza

public abstract class Pizza {
    String nazwa="Nazwa nieznana";
    public String getNazwa() {
        return nazwa;
    }
    public abstract double koszt();
}

Jak możemy zauważyć posiada ona jedynie zmienną nazwa. Najwyższa pora aby poznać także klasy dziedziczące po niej. A więc do dzieła

public class Magrarita extends Pizza{
    public Magrarita(){
        nazwa="Pizza Margarita";
    }
    @Override
    public double koszt() {
        return  40.99;
    }
}

public class Pepperoni extends Pizza{
    public Pepperoni(){
        nazwa="Pizza Pepperoni";
    }
    @Override
    public double koszt() {
        return 45.99;
    }
}

Obie klasy nadpisują metodę koszt która zwraca cenę danej pizzy a także jej nazwę. Ugryźmy teraz problem z innej strony i przyjrzyjmy się klasie abstrakcyjnej Skladniki

public abstract class Skladniki extends Pizza{
    public abstract String getNazwa() ;
}

Klasa ta ma za zadanie reprezentować poszczególne składniki pizzy. Kod do składników został zaprezentowany poniżej

public class SerMozarella extends Skladniki{
    Pizza pizza;
    public SerMozarella(Pizza pizza){
        this.pizza=pizza;
    }
    @Override
    public double koszt() {
        return pizza.koszt()+ 1.22;
    }
    @Override
    public String getNazwa() {
        return pizza.getNazwa()+ ", Ser Mozarella";
    }
}
public class SosCzosnkowy extends Skladniki{
    Pizza pizza;
    public SosCzosnkowy(Pizza pizza){
        this.pizza=pizza;
    }
    @Override
    public double koszt() {
        return (double) pizza.koszt()+ 1.42;
    }
    @Override
    public String getNazwa() {
        return pizza.getNazwa()+ ", Sos Czosnkowy";
    }
}

Jak możemy zaobserwować obie klasy dziedziczą po klasie abstrakcyjnej. Czas aby zasymulować działanie programu

public class Test {
    public static void main(String[] args){
        Pizza pizza= new Pepperoni();
        pizza= new SerMozarella(pizza);
        pizza= new SosCzosnkowy(pizza);
        System.out.println(pizza.getNazwa()+ " "+ pizza.koszt());
    }
}

Wynik sumulacji jest następujący

Pizza Pepperoni, Ser Mozarella, Sos Czosnkowy 48.63

Jak możemy zaobserwować przykład ten dowodzi iż możliwe jest przypisanie nowych klas do obiektu pizza które dodają koszt poszczególnych składników do pizzy co z kolei umożliwia rozpatrywanie każdej klasy z osobna. Umożliwia bardzo łatwe dodawanie nowych klas jak np. sos pomidorowy czy parmezan dzięki czemu nie łąmiemy zasady hermetyzacji.