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. 😉