2

I'm trying to teach myself some design patterns using a book that I was recommended, Head First Design Patterns. I came to the chapter on the Decorator Pattern, and although I understand the purpose of it, I'm a bit fuzzy on it's layout.

Here is their basic UML of the Decorator pattern: Imgur (Sorry for the link, but SE won't let me upload a photo here for some reason)

Here is how they wrote out the code:

public abstract class Component {
    String description = "Unknown Description";

    public String getDescription() {
        return description;
    }

    public abstract double cost();
}

public class ConcreteComponent extends Component {
    public ConcreteComponent() {
        description = "I am a concrete component";
    }

    public double cost() {
        return 1.99;
    }
}

public abstract class Decorator extends Component {
    public abstract String getDescription();
}

public class ConcreteDecorator extends Decorator {
    Component component;

    public ConcreteDecorator(Component component) {
        this.component = component;
    }

    public String getDescription() {
        return component.getDescription() + " with a decorator";
    }

    public double cost() {
        return .20 + component.cost();
    }
}

My question is, what is the need for a Decorator class in this situation? Why not leave getDescription() abstract and let ConcreteComponents and ConcreteDecorators implement it the way they need?

As a follow up, are there actual benefits to creating a Decorator class? This example doesn't seem to cover why it's useful or how it could be useful.

1 Answer 1

3

With a Decorator you are able to augment the code you are wrapping without changing it at all. And in some cases, not even having to know what it does.

The Open/Closed Principle states that

software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification

So, if you just made it abstract, what would happen if you had to then modify the description in your concrete implementation? You would have to modify your class.

Yes, this particular example is a little contrived. But, with this pattern, you can add decorators that augment a message (like in the design of Streams), or provide aspects that are orthogonal to the process (like logging or tracing) without touching or changing the code that the Decorator is wrapping.

Also, because a Decorator is a Component you can add a second Decorator without having to know that it wrapping a Decorator. In other words, this helps keep the Decorators separate from each other. This leads to code that is both decoupled and cohesive.

8
  • Okay, so which class exactly is supposed to be closed to change? From what I can tell, if I want to modify the description, I will have to modify Component or ConcreteComponent depending on how I implement description.
    – comscis
    Commented Jan 1, 2014 at 23:51
  • But not if you want to augment it (or Decorate it). Correct? How about if you wanted to Log every time getDescription was called in order to record performance statistics. So, Decorator allows us to add something to the call without touching the original. Commented Jan 1, 2014 at 23:52
  • In your answer, you talked about modifying the description in concrete implementation. Could you explain what you mean? There are two concrete implementations from what I can tell. I also don't quite get why you would want another Decorator class...
    – comscis
    Commented Jan 1, 2014 at 23:57
  • In the example above, if the ConcreteComponent was already written, and you wanted to add " with a decorator" to the description, you would then be forced to modify the ConcreteComponent class. Commented Jan 1, 2014 at 23:59
  • There is nothing stopping you from using many decorators. This pattern allows you to also decorate ConcreteDecorator because it is also a Component. As for when you would want to do this, it depends on the system you are building. You might want to add a decorator that Logs, Encrypts, and then Deletes the description etc. Commented Jan 2, 2014 at 0:03

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.