Wzorzec projektowy Dekorator

Jego zadaniem jest rozszerzenie funkcjonalności obiektu poprzez dynamiczne dołączenie dodatkowych zachowań.

  • Wzorzec ten pozwala na "dekorowanie" zachowania klasy, czyli zmianę jej funkcjonalności bez potrzeby dziedziczenia.
  • Jego działanie można upodobnić do dziedziczenia z tą rożnicą, że dziedziczenie rozszerza zachowanie klasy w trakcie kompilacji a dekoratory rozszerzają klasy w czasie działania programu.

Działanie

Dekorator zmienia operacje dowolnego Komponentu przez użycie dodatkowego kodu w stosunku do wywoływanej przy tym operacji obiektu dekorowanego.

Zalety

  • Większa ?elastyczność? programowanych rozwiązań niż w przypadku dziedziczenia - dynamiczny odpowiednik dziedziczenia obiekt można dowolnie "udekorować" podczas wykonania.
  • uproszczenia kodowania poprzez możliwość rozwoju szeregu klas o określonych funkjach zamiast umieszczania wszystkich zachowań w jednym obiekcie - rozbicie funkcjonalności.

Wady

  • Projekty, w ktorych jest używany, charakteryzują się mnogością małych podobnych do siebie obiektow, ktore rożnią się jedynie tym jak są ze sobą połączone. Poznanie i zrozumienie ich w celu modyfikacji może być przez to mocno utrudnione.
  • Nie można także korzystać w takich systemach z identyczności obiektow. Dekorator działa jak przezroczysta otoczka, ale z punktu widzenia identyczności obiekt udekorowany nie jest taki sam jak wejściowy.

Stosowalność

  • Kiedy chcemy w sposób jawny i dynamiczny dodac nowe zachowania do obiektu bez wpływu na pozostałe obiekty
  • Chcemy dodać nowe zachowania do obiektu, wg. Których istnieje możliwość że będą zmieniane w przyszłości
  • Kiedy rozszerzanie funkcjonalności poprzez podklasy przestaje być pratyczne, np. jeżeli do hierarchii klas musimy dodać nowe podklasy zmieniające zachowania każdego liścia z danej hierarchii. W danej sytuacji lepiej jest stworzyć nową podklasę klasy głównej, która będzie modyfikować odpowiednie zachowanie.

Struktura

Implementacja

public interface Komponent {
   public void action();
}
public class KonkretnyKomponent implements Komponent {
   public void action() {
       /* ciało metody */ }
}
public KonkretnyDekorator extends Dekorator {
   public void action() {
      super.action();
      dodanaMetoda();
   }
   private void dodanaMetoda(){
       /* ciało metody */
   }
}
public class Dekorator implements Komponent {
   Komponent kompJeden = new KonkretnyKomponent();
   public void action() {
       kompJeden.action();
   }
}