Potrebbe essere definito un pattern decoratore?

3

Voglio aggiungere alcuni metodi aggiuntivi strettamente correlati a Book senza estendere Book. Così ho trovato lo schema del decoratore.

La maggior parte degli esempi che ho visto sono ad es. estendere una classe decoratrice astratta che implementa un'interfaccia ecc.

Mi chiedo se questo potrebbe essere considerato come modello decoratore?

class Book { ... }

class MyBookDecorator {

  constructor ( Book book ) {
    this->book = book
  }

  extraMethod() {
    ...
  }
}

myBook = new MyBookDecorator( book );
myBook->extraMethod();

In caso contrario, questo è un modello valido da usare?

Grazie in anticipo!

    
posta Thomas Andersen 07.06.2016 - 21:19
fonte

2 risposte

5

No, non è davvero un motivo decoratore

Ma è un buon modo per comporre invece di ereditare.

Un decoratore è un oggetto che puoi avvolgere attorno a un altro oggetto, che altera il comportamento dell'oggetto, ma l'oggetto risultante è ancora usato come sarebbe l'oggetto originale. Puoi effettivamente racchiudere tanti decoratori attorno all'oggetto che desideri.

Nel tuo esempio estendi la classe per composizione e il risultato non può essere utilizzato come oggetto originale.

Un pattern decorator dovrebbe essere qualcosa del genere (esempio tratto dalla pagina wiki)

// Abstract decorator class - note that it implements Coffee interface
public abstract class CoffeeDecorator implements Coffee {
    protected final Coffee decoratedCoffee;

    public CoffeeDecorator(Coffee c) {
        this.decoratedCoffee = c;
    }

    public double getCost() { // Implementing methods of the interface
        return decoratedCoffee.getCost();
    }

    public String getIngredients() {
        return decoratedCoffee.getIngredients();
    }
}

// Decorator WithMilk mixes milk into coffee.
// Note it extends CoffeeDecorator.
class WithMilk extends CoffeeDecorator {
    public WithMilk(Coffee c) {
        super(c);
    }

    public double getCost() { // Overriding methods defined in the abstract superclass
        return super.getCost() + 0.5;
    }

    public String getIngredients() {
        return super.getIngredients() + ", Milk";
    }
}

// Decorator WithSprinkles mixes sprinkles onto coffee.
// Note it extends CoffeeDecorator.
class WithSprinkles extends CoffeeDecorator {
    public WithSprinkles(Coffee c) {
        super(c);
    }

    public double getCost() {
        return super.getCost() + 0.2;
    }

    public String getIngredients() {
        return super.getIngredients() + ", Sprinkles";
    }
}
    
risposta data 07.06.2016 - 21:30
fonte
1

Sì e no.

L'importante è che il "decoratore" debba agire il più possibile dell'originale, tranne per il punto in cui desideri differire.

Nelle lingue tipizzate, ciò avviene spesso rendendo sia Book che MyBookDecorator implementando la stessa interfaccia (chiamata in pratica IBook . Tutti i metodi che l'interfaccia dichiara sono quindi implementati come segue.

class MyBookDecorator implements IBook {
    construct(IBook book) {
        this->book = book;
    }

    int methodWeDoNotWantToChange(string arg1) {
        return this->book->methodWeDoNotWantToChange(arg1);
    }

    int getWord(int page, int line, int word) {
        string word = this->book->getWord(page, line, book);
        if (unsafeWords.contains(word) { return "*******"; }
        return word;
    }
}

In particolare: * è necessario implementare i tutti metodi che (I)Book fa, con la stessa firma. * il costruttore dovrebbe prendere un IBook‘, and not a Book 'in modo da poter combinare più decoratori. * I metodi che non ti interessano sono implementati come pass-through. * I metodi che ti interessano sono spesso anche pass-through, ma con un lavoro extra prima / dopo.

Puoi definire metodi extra, ma poi accoppi l'utente al tuo decpratore specifico, che non è una buona idea.

    
risposta data 07.06.2016 - 22:11
fonte