4

In book 'Head first design patterns', decorator chapter, it talks about issues when decorator deals with concrete type and cause problems. I am copying some Q&A in the chapter:

Q: I’m a little worried about code that might test for a specfic concrete component – say, HouseBlend – and do something, like issue a discount. Once I’ve wrapped the HouseBlend with decorators, this isn’t going to work anymore.

A: That is exactly right. If you have code that relies on the concrete component’s type, decorators will break that code. As long as you only write code against the abstract component type, the use of decorators will remain transparent to your code. However, once you start writing code against concrete components, you’ll want to rethink your application design and your use of decorators.

Could someone give simple examples on what it means that 'client' code is written against concrete type vs abstract type? And how the former cause trouble for decorator?

A sample test code of decorator in the book is like this:

public class StarbuzzCoffee {
    public static void main(String args[]) {
        Beverage beverage2 = new DarkRoast();
        beverage2 = new Mocha(beverage2);
        beverage2 = new Mocha(beverage2);
        beverage2 = new Whip(beverage2);
        System.out.println(beverage2.getDescription()
            + “ $” + beverage2.cost());
        ...
    }
}

Is this test code(also a client code) written against abstract type?

Thanks,

Ravindra babu
  • 37,698
  • 11
  • 250
  • 211
user1559625
  • 2,583
  • 5
  • 37
  • 75

2 Answers2

3

They're talking about code that checks the type of beverage2, for example

if (beverage2 instanceof DarkRoast) {
    <do_something>
}

Once you decorate beverage2 with a Mocha or Whip, it isn't a DarkRoast anymore.

Edit: I should also mention that often the use of instanceof indicates a poor design that doesn't use OO to its fullest, that said it is useful in some cases.

Vikdor
  • 23,934
  • 10
  • 61
  • 84
sceaj
  • 1,573
  • 3
  • 12
  • 24
0

As long as you only write code against the abstract component type, the use of decorators will remain transparent to your code

Yes. That's the way it should be.

You should not decorate new functionality specific to concrete decorator implementation. Once you do it, the purpose of decorator pattern is lost.

Decorator pattern works well due to abstract Decorator containing the interface itself ( using composition). It helps in reducing number of different combinations for different flavors.

I have implemented Decorator pattern for similar use-case. Have a look at this documentation link

When to Use the Decorator Pattern?

 Beverage beverage = new SugarDecorator(new LemonDecorator(new Tea("Assam Tea")));
 beverage.buildBeverage();

You will get output as 18 which is sum of Tea (10) + Lemon (5) + Sugar (3) :

Cost of:Assam Tea+Lemon +Sugar :18

For above example to work, you require some changes in abstract Decorator as explained in documentation link. Due to the composition of Beverage in Decorator abstract class, multiple flavours can be added easily.

You should never add business logic based on Concrete Decorator. One you incorporate intelligence of Concrete Decorator in your code, you lose flexibility of adding dynamic responsibilities independently.

Ravindra babu
  • 37,698
  • 11
  • 250
  • 211