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.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
package wzorceprojektowe1;
/** @author Utracki */
public abstract class Apartment {
public abstract float cena();
public abstract String wyposażenie();
}
package wzorceprojektowe1; /** @author Utracki */ public abstract class Apartment { public abstract float cena(); public abstract String wyposażenie(); }
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.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
package wzorceprojektowe1;
/** @author Utracki */
class room2beds extends Apartment {
@Override
public float cena() { return 270f; }
@Override
public String wyposażenie() { return "Pokój dwuosobowy"; }
}
package wzorceprojektowe1; /** @author Utracki */ class room2beds extends Apartment { @Override public float cena() { return 270f; } @Override public String wyposażenie() { return "Pokój dwuosobowy"; } }
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.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
package wzorceprojektowe1;
/** @author Utracki */
abstract class Wyposażenie extends Apartment{}
package wzorceprojektowe1; /** @author Utracki */ abstract class Wyposażenie extends Apartment{}
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:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
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";
}
}
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"; } }
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…

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
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());
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());
   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. 😉