The Decorator Pattern is a structural design pattern that allows behavior to be added to individual objects, dynamically, without affecting the behavior of other objects from the same class.
The Decorator Pattern wraps an object to add new behaviors or responsibilities. Each wrapper, or decorator, adds functionality to the base object while maintaining its interface.
Key features:
- Dynamic Behavior: Add responsibilities to objects dynamically at runtime.
- Composability: Combine multiple decorators to create complex behaviors.
- Open/Closed Principle: Extend an object's behavior without modifying its existing code.
- Customization: Add new behavior to individual objects without altering the original class.
- Scalability: Combine multiple decorators for complex use cases.
- Flexibility: Avoid subclassing by using composition to add behaviors.
The implementation of the Decorator Pattern can be found in:
Beverage.java
: Abstract component interface.Espresso.java
,HouseBlend.java
,DarkRoast.java
: Concrete components.CondimentDecorator.java
: Abstract decorator class.Mocha.java
,Whip.java
,Soy.java
: Concrete decorators.CoffeeHouse.java
: Client code to demonstrate the Decorator Pattern.
To see the Decorator Pattern in action, refer to the CoffeeHouse.java
file. It demonstrates how to dynamically add condiments to beverages using decorators.
classDiagram
class IObject {
+stuff()
}
class Object {
+stuff()
}
class Decorator {
- object : IObject
+stuff()
}
class ConcreteDecorator1 {
+stuff()
}
class ConcreteDecorator2 {
+stuff()
}
class ConcreteDecorator3 {
+stuff()
}
IObject <|-- Object
IObject <|-- Decorator
Decorator <|-- ConcreteDecorator1
Decorator <|-- ConcreteDecorator2
Decorator <|-- ConcreteDecorator3
Decorator o--> IObject
Note
If the UML above is not rendering correctly, you can view the diagram from the decorator_uml.png
file.
- The Decorator Pattern is ideal for dynamically extending the behavior of objects.
- It adheres to the Open/Closed Principle by allowing objects to be extended without modifying their code.
- Use it when subclassing becomes impractical or leads to an explosion of classes.