Wzorce projektowe (11)

Autor: Damian Chodorek • Opublikowany: 23 lipca 2015 • Ostatnia aktualizacja: 24 lipca 2015 • Kategoria: kursy, wzorce projektowe

Dekorator.

Dekorator to wzorzec obiektowy. Pozwala na dodanie nowej funkcjonalności do istniejących klas dynamicznie, podczas działania programu. Jest pewną alternatywą dla dziedziczenia, które rozszerza funkcjonalność programu podczas kompilacji (dekorator podczas działania programu).

Klasy

class Component{/*
klasa abstrakcyjna dla wszystkich konkretnych komponentów
*/};

class ConcreteComponent: public Component{/*
klasa definiująca obiekt, do którego można dodać jakąś funkcjonalność dynamicznie
*/};

class Decorator: public Component{/*
abstrakcyjna klasa dla konkretnych dekoratorów
*/};

class ConcreteDecorator: public Decorator{/*
klasa odpowiedzialna za dodawanie nowych funkcjonalności
*/};

class Client{/*
tworzy obiekty wykorzystujące wzorzec
*/};

Etapy działania

  1. Klient tworzy komponent i przekazuje go do konstruktora konkretnego dekoratora, który rozszerzy funkcjonalność
    komponentu.
  2. Następnie może tak stworzony obiekt przekazać do innego konkretnego dekoratora itd.
  3. Wynikiem końcowym jest obiekt, który może być przypisany do wskaźnika Component, posiadający wszystkie funkcjonalności jakie klient chce.

Konsekwencje

  • Wygodny sposób na dodawanie funkcjonalności do obiektów zamiast tworzenia nowych klas.
  • Narzut wydajnościowy.

Przykład

#include <iostream>
using namespace std;

///klasa abstrakcyjna Okno
class Okno
{
public:
    virtual void rysuj()=0;
    virtual string pobierzOpis()=0;
    virtual ~Okno() {}
};

///implementacja zwykłego okna
class ZwykleOkno : public Okno
{
public:
    void rysuj()
    {
        ///rysujemy zwykle okno
    }

    string pobierzOpis()
    {
        return "Zwykle okno";
    }
};

///abstrakcyjna klasa dekorator
class OknoDekorator : public Okno
{
public:
    OknoDekorator(Okno* dekOk)
    {
        this->dekorowaneOkno=dekOk;
    }

protected:
    Okno* dekorowaneOkno;
};

///pierwszy konkretny dekorator - dodaje pionowy pasek
class PionowePrzewijanieDek : public OknoDekorator
{
public:
    PionowePrzewijanieDek(Okno* dekOk): OknoDekorator(dekOk)
    {
    }

    ~PionowePrzewijanieDek()
    {
        delete dekorowaneOkno;
    }

    void rysuj()
    {
         dekorowaneOkno->rysuj();
         dorysujPionowyPasek();
    }

    string pobierzOpis()
    {
        return dekorowaneOkno->pobierzOpis() + ", z pionowym paskiem"
                    +" przewijania";
    }

private:
    void dorysujPionowyPasek()
    {
        ///...
    }
};  


///drugi konkretny dekorator dodaje poziomy pasek
class PoziomePrzewijanieDek : public OknoDekorator
{
public:
    PoziomePrzewijanieDek(Okno* dekOk): OknoDekorator(dekOk)
    {
    }

    ~PoziomePrzewijanieDek()
    {
        delete dekorowaneOkno;
    }

    void rysuj()
    {
        dekorowaneOkno->rysuj();
        dorysujPoziomyPasek();
    }

    string pobierzOpis()
    {
        return dekorowaneOkno->pobierzOpis() + ", z poziomym paskiem"
                        +" przewijania";
    }

private:
    void dorysujPoziomyPasek()
    {
        ///...
    }
}; 


int main(int argc, const char* argv[])
{
  Okno* oknoPrzewijane=new PoziomePrzewijanieDek( new
        PionowePrzewijanieDek( new ZwykleOkno ) );

  cout<<oknoPrzewijane->pobierzOpis()<<endl;
}

część 12

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany.