Navigacija
Lista poslednjih: 16, 32, 64, 128 poruka.

Decorator pattern, implementacija + (brisanje odredjenog dekoratora)

[es] :: C/C++ programiranje :: Decorator pattern, implementacija + (brisanje odredjenog dekoratora)

[ Pregleda: 1967 | Odgovora: 0 ] > FB > Twit

Postavi temu Odgovori

Autor

Pretraga teme: Traži
Markiranje Štampanje RSS

glorius
Damir Nikolic
C++ developer
SR

Član broj: 4366
Poruke: 428
*.dynamic.isp.telekom.rs.

ICQ: 208550327


+14 Profil

icon Decorator pattern, implementacija + (brisanje odredjenog dekoratora)13.08.2013. u 20:35 - pre 83 meseci
Malo sam proucavao Design Patterns ovih dana i radio sam sa Decorator patternom.
U toku analize sam primetio da moze doci do zahteva da se neki od dekoratora izbrise u runtime i proucavajuci knjigu koja opisuje dekorator pattern nisam naisao na taj feature tako da sam ga sam implementirao pa sam odlucio da to podelim sa vama.
Po meni je to koristan feature tako da, ako vam je interesantno, slobodno mozete da prosirite kod, ispravite ili da se igrate njime :)

Inace je kod implementiran genericki i funkcionalnost dozvoljava dodavanje dekoratora po sistemu add/remove.

Nisam nesto mnogo sredjivao kod, verovatno se mozda nadje i neki bugcic, posto je ovo generalno shtura implementacija ideje, imena promenljivih su smisljana on-the-fly, nemojte mi zameriti na tome...

Svaka kritika i savet su pozeljni.

Evo i koda:

Code:


#include <QCoreApplication>

// helper za proveru validnosti iteratora
#define CHECK_DECO_ITER(iter) \
    (iter != m_decos.end())

// klasa iz koje se izvodi bazna klasa koja namerava da se dekorisana
template <typename T>
class DecoHelper
{
protected:
    T* m_pDecoratedObject;
public:
    void setDecoratedObject(T* pObject)
    {
        m_pDecoratedObject = pObject;
    }
};

// Srce sistema. Manager dekorator klasa
template <typename T>
class DecoratorManager
{
    std::list<T*> m_decos;
    typedef typename std::list<T*>::iterator DecosIter;
    T* m_pDecoratee;
public:
    DecoratorManager(T* pDecoratee)
    {
        m_pDecoratee = pDecoratee;
    }

    void applyDecorator(T* pDecorator)
    {
        if(!m_decos.size())
        {
            pDecorator->setDecoratedObject(m_pDecoratee);
        }
        else
        {
            pDecorator->setDecoratedObject(m_decos.front());
        }

        m_decos.push_front(pDecorator);
    }

    T* finalDeco() const
    {
        return m_decos.front();
    }

    void removeDecorator(int index)
    {
        DecosIter iterDecos = m_decos.begin();

        int count = 0;
        while(iterDecos != m_decos.end() && count < index)
        {
            ++count;
            ++iterDecos;
        }

        DecosIter previous = m_decos.end();
        DecosIter next = m_decos.end();

        if(iterDecos != m_decos.begin())
        {
            previous = iterDecos;
            std::advance(previous, -1);
        }

        next = iterDecos;

        if(next != m_decos.end())
        {
            std::advance(next, 1);
        }

        if(iterDecos != m_decos.end())
        {
            redecorate(previous, next);
            m_decos.remove(*iterDecos);
        }
    }
private:
    void redecorate(DecosIter prev, DecosIter next)
    {
        if(!CHECK_DECO_ITER(prev) && !CHECK_DECO_ITER(next))
        {
            // do nothing
        }
        else if(CHECK_DECO_ITER(prev))
        {
            if(CHECK_DECO_ITER(next))
            {
                (*prev)->setDecoratedObject(*next);
            }
            else
            {
                (*prev)->setDecoratedObject(m_pDecoratee);
            }
        }
    }
};

// Test klase koje pokazuju kako se koriste gore navedene klase za manipulaciju Dekoratorima

class Element : public DecoHelper<Element>
{
public:
    virtual void print() const
    {
        printf("I am an element\n");
    }
};

class Decorator : public Element
{
public:
    virtual void print() const
    {
        m_pDecoratedObject->print();
    }
};

class Border : public Decorator
{
    int m_nWidth;
public:
    Border(int width) : m_nWidth(width)
    {}

    virtual void print() const
    {
        printf("I am a border, my width is %d.\n", m_nWidth);
        Decorator::print();
    }
};

class Scroller : public Decorator
{
    int m_nMin;
    int m_nMax;
    int m_nPos;
public:
    Scroller(int nMin, int nMax, int nPos)
        : m_nMin(nMin)
        , m_nMax(nMax)
        , m_nPos(nPos)
    {}

    virtual void print() const
    {
        Decorator::print();
        printf("I am a scroller: Min: %d, Max: %d, Pos: %d\n", m_nMin, m_nMax, m_nPos);
    }
};

int main(int argc, char *argv[])
{
    //QCoreApplication a(argc, argv);

    // Ovako bi izgledala standardna inicijalizacija bez DecoHelper i DecoratorManager klasa

    // Podrazumeva se da i Border i Scroller u konstruktorima uzimaju Element objekat

    // 1. Element* pElement = new Border( new Scroller( new Element ), 0, 100, 39 ), 4 );

    // 2. Element* pElement = new Element;
    //    Element* pScroller = new Scroller(pElement, 0, 100, 39)
    //    Element* pBorder = new Border(pScroller, 4);

                                                   //  Decorator index
    DecoratorManager<Element> dm(new Element);
    dm.applyDecorator(new Scroller(0, 100, 39));   //         1
    dm.applyDecorator(new Border(4));              //         0
    dm.removeDecorator(1); // removes scroller
    dm.finalDeco()->print();
}


EOF
 
Odgovor na temu

[es] :: C/C++ programiranje :: Decorator pattern, implementacija + (brisanje odredjenog dekoratora)

[ Pregleda: 1967 | Odgovora: 0 ] > FB > Twit

Postavi temu Odgovori

Navigacija
Lista poslednjih: 16, 32, 64, 128 poruka.