Also known as Wrapper.
Dynamically attach responsabilities to an object.
It provides a flexible alternative to subclassing for extending functionality.
You should use the Decorator pattern in the following cases :
- You want to provide individual objects (not an entire class) with a new behaviour.
- You want to add responsabilities dynamically and transparently.
- When the alternative (extension by subclassing) is impractical :
- When it would produce an explosion of subclasses to support every combination.
- The class definition is hidden or unavailable for subclassing.
Participants
- Component : The interface for objects that can have responsabilities dynamically added.
- ConcreteComponent : The objects to which responsabilities can be added.
- Decorator : Defines an interface that conforms to Component's interface. Maintain a reference to a Component object (wrappee).
- ConcreteDecorator : The object that adds responsabilities to ConcreteComponent.
How to implement
- Create an interface and declare the methods common to both the primary Component and the optional layers.
- Create your ConcreteComponent class with its base behaviour.
- Create your Decorator class with a field storing a reference to the wrapped object (Your Component). The Decorator will delegate all the work (i.e. except for the additional responsabilities) to the wrapped object.
- Create your ConcreteDecorator and implement the additional responsabilities before or after the call to the wrappee behaviour.
Note : The Client can then create and compose ConcreteDecorators in the way he needs.
Note : UML class diagram taken from here
Pros
- Extend an object's behaviour without subclassing.
- Add responsabilities at runtime.
- Combine behaviours (decorators composition) to suit your needs.
- Single responsability principle : Divide monolithic classes into many classes with unique responsabilities.
Cons
- It is hard to remove a decorator once it has been added.
- Order : It might be difficult to implement decorators in a way they are order-independant.
Here are some usefull ressources :
- A Refactoring guru article.
- A complete example here