Umożliwia dodanie nowej funkcjonalności dynamicznie podczas
działania programu.
Wzorzec dekoratora polega na opakowaniu oryginalnej klasy
w nową klasę "dekorującą". Zwykle przekazuje się oryginalny
obiekt jako parametr konstruktora dekoratora, metody dekoratora
wywołują metody oryginalnego obiektu i dodatkowo implementują
nową funkcję.
Dekoratory są alternatywą dla dziedziczenia. Dziedziczenie
rozszerza zachowanie klasy w trakcie kompilacji,
w przeciwieństwie do dekoratorów,
które rozszerzają klasy w czasie działania programu.
Jest to dosyć jasny wzorzec wiec szybko przejde do przykładu.
1. Na początek tworzymy interfejs Okno.
interface Okno { public void rysuj(); // rysuje Okno na ekranie public String pobierzOpis(); // zwraca opis Okna }2. Implementacja zwykłego okna bez pasków przewijania.
class ZwykłeOkno implements Okno { public void rysuj() { // rysuj okno } public String pobierzOpis() { return "zwykłe okno"; } }
3. Abstrakcyjna klasa dekorator - implementuje interfejs Okno.
Klasa OknoDekorator przechowuje w sobie jako pole Okno.
To właśnie okno będzie dekorowane, dlatego więc do konstruktora
klasy przekazane zostanie okno, które będzie mialo zostać udekorowane.
Jest to klasa abstrakcyjna wiec nie jest wymagane, aby implementowac
wszystkie metody z interfejsu Okno.
abstract class OknoDekorator implements Okno { protected Okno dekorowaneOkno; // dekorowane Okno public OknoDekorator(Okno dekorowaneOkno) { this.dekorowaneOkno = dekorowaneOkno; } }
4. Czas na pierwszy dekorator dodający pionowe paski przewijania.
Każdy dekorator na swój sposób implementuje/dekoruje metode
rysuj(). W klasie PionowePrzewijanieDekorator w metodzie rysuj()
wywolujemy tez metode rysuj() na rzecz obiektu dekorowaneOkno.
class PionowePrzewijanieDekorator extends OknoDekorator { public PionowePrzewijanieDekorator (Okno dekorowaneOkno) { super(dekorowaneOkno); } public void rysuj() { rysujPionowyPasekPrzewijania(); dekorowaneOkno.rysuj(); } private void rysujPionowyPasekPrzewijania() { // rysuj pionowy pasek przewijania } public String pobierzOpis() { return dekorowaneOkno.pobierzOpis() + ", z pionowym paskiem przewijania"; } }5. Drugi inny dekorator dodający poziome paski przewijania.
class PoziomePrzewijanieDekorator extends OknoDekorator { public PoziomePrzewijanieDekorator (Okno dekorowaneOkno) { super(dekorowaneOkno); } public void rysuj() { rysujPoziomyPasekPrzewijania(); dekorowaneOkno.rysuj(); } private void rysujPoziomyPasekPrzewijania() { // rysuj poziomy pasek przewijania } public String pobierzOpis() { return dekorowaneOkno.pobierzOpis() + ", z poziomym paskiem przewijania"; } }
6. Na sam koniec program testowy, który tworzy obiekt klasy Okno, dekoruje go
poziomymi i pionowymi paskami przewijania i wypisuje jego opis. Prosze zwrócic
uwage na sposób w jaki tworzymy dekorowane okno. Najpierw wywolujemy new dla
pierwszego dekoratora, nastepnie do konstruktora tego dekoratora przekazujemy
new drugiego dekoratora. Wszystko sie zgadza oba dekoratory przyjmuja jako argument
do konstruktora obiekt klasy Okno oraz oba dekoratory dziedzicza
po klasie OknoDekorator, a ta z koleji implementuje interfejs Okno.
Na samo koniec inicjalizacji dekorowanego okna do konstruktora drugiego
dekoratora przekazujemy zwykłeOkno.
W następnej linijce pobieramy opis. Można dzięki takiemu zabiegowi łatwo sprawdzić
czy wszystko się zgadza.
public class DekorowaneOknoTest { public static void main(String[] args) { // utwórz dekorowane Okno z poziomymi i pionowymi paskami przewijania Okno dekorowaneOkno = new PoziomePrzewijanieDekorator( new PionowePrzewijanieDekorator(new ZwykłeOkno())); // wypisz opis Okna System.out.println(dekorowaneOkno.pobierzOpis()); } }
Dekorator jest jednym z protszych wzorców. Myśle, że powyższy przykład dość
dobrze odzwierciedlił zasade działania tego wzroca. Na koniec tradycyjnie
diagram klas :
Brak komentarzy:
Prześlij komentarz