Che tipo di base per Decorator: interfaccia, classe astratta, non astratta

3

Quale dovrebbe essere nella parte superiore dell'albero di ereditarietà del pattern di progettazione Decorator? Intendo la base per entrambi i componenti e decoratori

  • Classe non astratta : ha campi dati, metodi implementa
  • classe astratta : ha campi dati, ha solo metodi astratti (puramente virtuali)
  • interfaccia : nessun campo dati, ha solo metodi astratti (puramente virtuali)
  • classe astratta & interfaccia : l'interfaccia è la base del decoratore, la classe astratta è la base per i componenti decorati

Semplice esempio

  • IText - l'interfaccia dichiara il metodo getContent()
  • AbstractText - la classe astratta dichiara il metodo getContent() e definisce txt dati campo
  • Text - la classe non astratta, generale, può essere utilizzata anche come base per altre classi
  • HelloWorld - classe non astratta, più specifica di Text
  • HelloSomeone - classe non astratta, estende Text con il campo dati name
  • Decorator classe astratta per decoratori (potrebbe essere ridondante?)
  • PrefixDecorator prefisso di classe decoratore getContent() con un prefisso di stringa
  • SuffixDecorator decoratore suffissi di classe getContent() con un suffisso di stringa
  • getContent() metodo che dovrebbe restituire txt con dati aggiuntivi facoltativi (suffissi e prefissi dai decoratori, campo name nella classe HelloSomeone )

Quale classe base dovrebbe essere scelta?

  • classe non astratta

  • classeastratta

  • interfaccia

  • classeastratta&interfaccia

Codice per l'ultimo esempio

#include <iostream> 
#include <string> 
using namespace std;

/* Base for decorator & abstract: no fields, getContent()  is pure virtual */
class IText {
public:
    virtual string getContent() = 0;
    virtual ~IText() { }
};

/* Base: has a field, getContent()  is pure virtual */
class AbstractText : public IText {
protected: 
    string txt;
public:
    virtual ~AbstractText() { cout << " AbstractText dtor" << endl; }
    AbstractText(string t = "...") : txt(t) { }
    virtual string getContent() = 0;
};

/* Concrete, general */
class Text : public AbstractText {
public:
    virtual ~Text() { cout << " Text dtor" << endl; }
    Text(string t) : AbstractText(t) { }
    virtual string getContent() { return txt; }
};

/* Concrete, more specific */
class HelloWorld : public AbstractText {
public:
    virtual ~HelloWorld() { cout << " HelloWorld dtor" << endl; }
    HelloWorld() : AbstractText("Hello world") {}
    virtual string getContent() { return txt; }
};

/* Additional field */
class HelloSomeone : public AbstractText {
private:
    string name;
public:
    virtual ~HelloSomeone() { cout << " HelloSomeone dtor" << endl; }
    HelloSomeone(string n) : AbstractText("Hello, "), name(n) { }
    string getContent() { return (txt + name + "!"); }
};


class Decorator : public IText {
public:
    virtual string getContent() = 0;
    virtual ~Decorator() { cout << " Decorator dtor" << endl; }
};

class PrefixDecorator : public Decorator {
private:
    IText *t;
public:
    PrefixDecorator(IText *te)  { t = te; }
    virtual ~PrefixDecorator() { cout << " PrefixDecorator dtor" << endl; delete t; }
    virtual string getContent() { return "---" + t->getContent(); }
};

class SuffixDecorator : public Decorator {
private:
    IText *t;
public:
    SuffixDecorator(IText *te)  { t = te; }
    virtual ~SuffixDecorator() { cout << " SuffixDecorator dtor" << endl; delete t; }
    virtual string getContent() { return t->getContent() + "---"; }
};

int main() {
    IText *t = new Text("some text");
    IText *hw = new HelloWorld();
    IText *hs = new HelloSomeone("Mark");
    cout << t->getContent() << endl;
    cout << hw->getContent() << endl;
    cout << hs->getContent() << endl;
    t = new PrefixDecorator(t);
    hw = new PrefixDecorator(hw);
    hw = new SuffixDecorator(hw);
    cout << t->getContent() << endl;
    cout << hw->getContent() << endl;
    cout << "DELETE Text" << endl;
    delete t;
    cout << "DELETE Helloworld" << endl;
    delete hw;
    cout << "DELETE HelloSomeone" << endl;
    delete hs;
}
    
posta user2314351 01.04.2015 - 10:50
fonte

2 risposte

2

What should be at the top of inheritance tree of Decorator design pattern?

Come discriminare:

  • classe non astratta - Solo se ha senso nel codice per istanziarlo nel codice client (vedi anche: sostituzione liskov)
  • interfaccia di classe astratta o - caso più comune; Questo è quando non ha senso che il codice client lo istanziasse; Per distinguere tra classe astratta e interfaccia: se osservi il tuo codice e scopri che tutte le specializzazioni hanno dati in comune, spostali nella classe base (altrimenti rimani con l'interfaccia).
  • Interfaccia
  • classe astratta e - se ci sono due casi in cui una parte delle specializzazioni ha codice comune e una parte no, estrai codice comune per separare la classe e finisci con entrambi i casi .

I miei criteri di solito non derivano da alcune regole pure che rispetto per implementare il decoratore; Invece, cerco di ottimizzare per la manutenzione anziché la purezza.

Puoi anche vedere che non distinguo particolarmente tra classi astratte e interfacce; questo perché in C ++ non ci sono interfacce, solo classi astratte (quindi la distinzione sembra un po 'artificiale).

    
risposta data 01.04.2015 - 16:28
fonte
1

Dipende interamente da ciò che vuoi. Queste variazioni esistono per tua comodità, non perché un modo è migliore di un altro.

Personalmente sono parziale alla classe non astratta, perché richiede il minor numero di classi, che a mio parere è sempre un vantaggio. Tuttavia, potresti trovarti nella situazione in cui è presente una classe AbstractText o IText e un'implementazione Text , nel qual caso puoi modellare il tuo pattern Decorator di conseguenza.

Se decidi di scegliere la variazione di classe non astratta, è probabilmente la più semplice da adattare alle altre varianti in seguito poiché è solitamente più facile aggiungere classi che rimuoverle, quindi darei la classe non astratta variazione una prova.

    
risposta data 01.04.2015 - 12:54
fonte

Leggi altre domande sui tag