Wzorzec strukturalny Decorator pewnie spodoba się osobom zmęczonym tworzeniem wielu klas potomnych w procesie dziedziczenia, gdy trzeba powołać do życia obiekty podobne do siebie ale nieco inaczej skonfigurowane.

Wyobraźmy sobie tematykę hotelową, gdzie w 300 identycznych z założenia pokojach hotelowych chcemy uwzględnić po pierwsze różnice infrastrukturalne wynikające z cech konstrukcyjnych, a następnie różnice w wyposażeniu będące skutkiem bądź ustalenia konkretnego poziomu komfortu bądź zamówienia klienta.
W “standardowym” wykonaniu powołalibyśmy do życia 300 instancji klas zawierających konkretne informacje o indywidualnych cechach każdego z obiektów… lub co najwyżej zastosowalibyśmy lawinowe dziedziczenie co i tak doprowadziłoby do rozbudowanego kodu z dużą ilością if’ów i case’ów. Tutaj właśnie wchodzi do gry propozycja utworzenia kodu z wykorzystaniem wzorca Dekorator.

W rezultacie otrzymaliśmy obiekty zawierające niezbędne informacje o oczekiwanym rezultacie i przygotowane w czytelny, prosty do rozbudowy sposób.

Jak zawsze… chodzi o kod

Stwórzmy pierwszą klasę Apartment… aby umożliwić powiązanie jej z konkretnym lokalem w hotelu.

package wzorceprojektowe1;
/**  @author Utracki  */

public abstract class Apartment {
    public abstract float cena();
    public abstract String wyposażenie();
}

Teraz już mając zaczątek naszego hotelu i wspomnieliśmy już że są w nim pokoje 😉 możemy zacząć tworzyć odwzorowanie fizycznej ich postaci dla każdego istniejącego wariantu.

package wzorceprojektowe1;
/**  @author Utracki  */

class room2beds extends Apartment {
    @Override
    public float cena() { return 270f; }
    @Override
    public String wyposażenie() { return "Pokój dwuosobowy"; }
}

Nadszedł już czas aby zagospodarować nasz pokój wstawiając jego wyposażenie… Będziemy do tego potrzebowali dodatkowej publicznej klasy (abstrakcyjnej), która umożliwi nam wzbogacenie pokoju o niezbędne jego akcesoria.

package wzorceprojektowe1;
/**  @author Utracki  */

abstract class Wyposażenie extends Apartment{}

Pozostało już teraz tylko zaimplementować całe wyposażenie jakie możemy wstawić do tego pokoju. W tym celu odpowiednio multiplikujemy poniższy kod:

package wzorceprojektowe1;
/**  @author Utracki  */

class TV extends Wyposażenie {
    private Apartment pokój;
    
    public TV(Apartment pokój) {
        this.pokój = pokój;
    }

    @Override
    public float cena() {
        return pokój.cena()+50f;
    }

    @Override
    public String wyposażenie() {
        return pokój.wyposażenie()+ " z TV";
    }
    
    
}

Na koniec pozostało już tylko pokazać jak użyć powyższej struktury…

   public static void main(String[] args) {

      Apartment room2beds = new room2beds();
      
      System.out.println("Pokój dwuosobowy cena: " + room2beds.cena());
      System.out.println("Wyposażenie pokoju to: " + room2beds.wyposażenie());
        
      Apartment room2beds_TV = new TV(room2beds);
      System.out.println("Pokój dwuosobowy cena: " + room2beds_TV.cena());
      System.out.println("Wyposażenie pokoju to: " + room2beds_TV.wyposażenie());
      

Zadanie: Przygotuj prostą demonstrację z wykorzystaniem wzorca, gdzie w przykładowym hostelu znajduje się 30 pokojów od 1-osobowych po 5-osobowe. Jedne wyposażone w TV, inne w jaccuzi… łóżka podwójne (małżeńskie) lub pojedyncze… itp.

Przygotuj program, który będzie pokazywał obłożenie takiego hostelu (poziom rezerwacji pokojów) z informacją jakie zasoby i w jakim stopniu są zajęte… np. wynajem kanału dla dorosłych itp. 😉