3

I want to add some extra methods closely related to Book without extending Book. So I found the decorator pattern.

Most examples I have seen are eg. extending an abstract decorator class which implements an interface etc.

I am wondering if this could be considered as decorator pattern?

class Book { ... }

class MyBookDecorator {

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

  extraMethod() {
    ...
  }
}

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

If not, is this a valid pattern to use?

Thank you in advance!

1
  • What you have looks more like the adaptor pattern. You are wrapping Book up so it can be used in a non-book context.
    – Daniel T.
    Commented Jun 7, 2016 at 23:29

2 Answers 2

5

No it is not really a decorator pattern

But it is a good way to compose instead of just inheriting.

A decorator is an object you can wrap around another object, that alters the behavior of the object, but the resulting object is still used as the original object would be. You can actually wrap as many decorators around the object you want.

In your example you are extending the class by composition and the result can't be used as the original object.

A decorator pattern would be something like this (example taken from wiki page)

// 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";
    }
}
1
  • 1
    It's probably worth mentioning one or two other implementation techniques rather than showing a complete code example, as this might give someone the impression that "decorator pattern" is synonymous with "derived class that adds methods". But +1 for the good answer.
    – Ixrec
    Commented Jun 7, 2016 at 19:57
1

Yes and no.

The important thing is that the 'decorator' needs to act as much as possible as the original, except for where you want it to differ.

In typed languages, this is often done by making both Book and MyBookDecorator implementing the same interface (commenly called IBook. All the methods the interface declares are then implemented as follows.

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 particular: * you need to implement all methods that (I)Book does, with the same signature. * the constructor should take an IBook‘, and not aBook` so that you can combine multiple decorators. * methods you do not care about are implemented as pass-through. * methods you do care about are often also pass-through, but with extra work before/after.

You can define extra methods, but then you couple the user to your specific decprator, which is not a good idea.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.