Add behavior to individual objects dynamically without altering their structure β a flexible alternative to subclassing.
π§ What is the Decorator Pattern?
The Decorator Pattern is a structural design pattern that allows you to:
- Attach additional responsibilities to objects at runtime
- Wrap objects with other objects that enhance behavior
- Maintain the original objectβs interface
π¦ Use Cases (Real-World)
Context | Example |
---|---|
β Coffee Shop | Add milk, sugar, etc. to base beverage dynamically |
π§Ύ Billing System | Add discounts, taxes, coupons to final price |
π I/O Streams (Java) |
BufferedReader , DataInputStream , GZIPOutputStream
|
π‘οΈ Security Layering | Add logging, auth, audit, throttling to requests |
π§ͺ Testing Mocks | Mock + Spy + Log enhancement |
π― When to Use It?
β Use when:
- You need to add features to objects dynamically and transparently
- You want to avoid subclass explosion
- You want to compose behavior in a flexible way
π« Avoid if:
- Object configuration is overly complex
- All variations are known at compile time (prefer inheritance)
π§± Pattern Structure
Component | Role |
---|---|
Component (interface) | Declares the core operation |
ConcreteComponent | The base implementation |
Decorator (abstract) | Holds a reference to a Component + delegates |
ConcreteDecorator | Adds extra behavior before/after delegate calls |
π UML Diagram
+------------------+
| Component | <<interface>>
+------------------+
| +operation() |
+------------------+
β²
|
+-------------------+
| ConcreteComponent |
+-------------------+
| +operation() |
+-------------------+
β²
|
+-------------------+
| Decorator | <<abstract>>
+-------------------+
| - component: Component
| +operation() |
+-------------------+
β²
+--------------------------+
| ConcreteDecoratorA |
+--------------------------+
| +operation() |
+--------------------------+
β Coffee Shop Example in Java
β
Beverage.java
public interface Beverage {
String getDescription();
double getCost();
}
β
Espresso.java
(ConcreteComponent)
public class Espresso implements Beverage {
@Override
public String getDescription() {
return "Espresso";
}
@Override
public double getCost() {
return 100.0;
}
}
β
BeverageDecorator.java
(Abstract Decorator)
public abstract class BeverageDecorator implements Beverage {
protected Beverage beverage;
public BeverageDecorator(Beverage beverage) {
this.beverage = beverage;
}
}
β
MilkDecorator.java
(ConcreteDecorator)
public class MilkDecorator extends BeverageDecorator {
public MilkDecorator(Beverage beverage) {
super(beverage);
}
@Override
public String getDescription() {
return beverage.getDescription() + ", Milk";
}
@Override
public double getCost() {
return beverage.getCost() + 20.0;
}
}
β
SugarDecorator.java
public class SugarDecorator extends BeverageDecorator {
public SugarDecorator(Beverage beverage) {
super(beverage);
}
@Override
public String getDescription() {
return beverage.getDescription() + ", Sugar";
}
@Override
public double getCost() {
return beverage.getCost() + 10.0;
}
}
β
Client.java
public class DecoratorClient {
public static void main(String[] args) {
Beverage espresso = new Espresso();
System.out.println("Order 1: " + espresso.getDescription() + " | βΉ" + espresso.getCost());
Beverage customCoffee = new MilkDecorator(new SugarDecorator(new Espresso()));
System.out.println("Order 2: " + customCoffee.getDescription() + " | βΉ" + customCoffee.getCost());
}
}
π§ͺ Output
Order 1: Espresso | βΉ100.0
Order 2: Espresso, Sugar, Milk | βΉ130.0
β¨ Benefits
Advantage | Explanation |
---|---|
β Flexible composition | Add features without changing existing classes |
β Open/Closed Principle | Extend behavior via composition |
β Reuse & layering | Chain decorators to build behavior stacks |
β No subclass explosion | Avoid subclassing for each variation |
β οΈ Limitations
- ποΈ Complex configuration if decorators are stacked dynamically
- π§© Debugging stack layers may be harder than single-class hierarchies
π§Ύ Summary
Feature | Value |
---|---|
Type | Structural |
Primary Intent | Add behavior at runtime |
Key Concepts Used | Composition, Delegation |
Java Real Usage |
InputStream , Logger , UI themes, Spring AOP |
Top comments (0)