Real World Example
Imagine you run a car service shop offering multiple services. Now how do you calculate the bill to be charged? You pick one service and dynamically keep adding to it the prices for the provided services till you get the final cost. Here each type of service is a decorator.
In Plain Words
Decorator pattern lets you dynamically change the behavior of an object at run time by wrapping them in an object of a decorator class.Wikipedia Definition
In object-oriented programming, the decorator pattern is a design pattern that allows behavior to be added to an individual object, either statically or dynamically, without affecting the behavior of other objects from the same class. The decorator pattern is often useful for adhering to the Single Responsibility Principle, as it allows functionality to be divided between classes with unique areas of concern.
Programmatic Example
Let’s take coffee for example. First of all we have a simple coffee implementing the coffee interface:Key Participants
Component
Component
Defines the interface for objects that can have responsibilities added to them (in our example:
Coffee interface)Concrete Component
Concrete Component
Defines an object to which additional responsibilities can be attached (in our example:
SimpleCoffee)Decorator
Decorator
Maintains a reference to a Component object and defines an interface that conforms to Component’s interface
Concrete Decorator
Concrete Decorator
Adds responsibilities to the component (in our example:
MilkCoffee, WhipCoffee, VanillaCoffee)Decoration Flow
When to Use?
Use the Decorator pattern when:
- You need to add responsibilities to individual objects dynamically and transparently
- You need to add responsibilities that can be withdrawn
- Extension by subclassing is impractical or impossible
- You want to avoid an explosion of subclasses to support every combination
Benefits
- More Flexibility: More flexible than static inheritance
- Avoids Feature-Laden Classes: Allows you to add functionality incrementally
- Single Responsibility: Divide functionality between classes with unique areas of concern
- Runtime Composition: Can add/remove responsibilities at runtime
Considerations
Decorator vs Inheritance
| Aspect | Inheritance | Decorator |
|---|---|---|
| Timing | Compile-time | Runtime |
| Flexibility | Static | Dynamic |
| Combinations | All combinations need separate classes | Mix and match decorators |
| Modification | Modifies class | Wraps object |
Real-World Applications
- I/O Streams in Java (BufferedReader, InputStreamReader)
- GUI components (adding borders, scrollbars)
- Middleware in web frameworks
- Logging, caching, validation wrappers
Related Patterns
- Adapter: Changes an interface; Decorator enhances responsibilities
- Composite: Decorator can be viewed as a degenerate composite with only one component
- Strategy: Decorator lets you change the skin of an object; Strategy lets you change the guts