🍕 Level Up Your Java & Design Pattern Skills!
Enjoying intuitive, real-world programming examples? Subscribe to Ram N Java for clean code, design architecture, and beginner-friendly tutorials.
🔔 Subscribe to Ram N JavaUnderstanding the Decorator Design Pattern
The Decorator Pattern is a structural design pattern that lets you attach additional responsibilities, properties, or behaviors to individual objects dynamically at runtime without affecting the behavior of other objects from the same class.
Instead of relying on rigid, complex class hierarchies created by inheritance, the Decorator Pattern uses object composition to wrap objects inside flexible decorators.
Real-Time Analogy: Customizing Your Pizza
Consider ordering a custom pizza at your favorite restaurant:
- You start with a base Plain Pizza (the dough and base sauce).
- Customer 1 adds Chicken Topping.
- Customer 2 adds Extra Cheese and Chicken together.
If you tried solving this with inheritance, you would have to write dedicated classes for every possible combination (PlainPizzaWithCheese, PlainPizzaWithCheeseAndChicken, and so on). This leads directly to class explosion.
With the Decorator Pattern, each topping acts as an independent decorator wrapping the base pizza, calculating costs, and building descriptions dynamically!
Core Architecture Breakdown
1. Component Interface
Defines the contract common to both the plain pizza and any toppings added on top:
public interface Pizza {
String makePizza();
}
2. Concrete Component
The baseline object that fulfills the initial operation:
public class PlainPizza implements Pizza {
@Override
public String makePizza() {
return "Plain Dough Pizza";
}
}
3. Abstract Decorator (Wrapper)
Implements Pizza and maintains a reference to an inner Pizza instance:
public abstract class PizzaDecorator implements Pizza {
protected Pizza specialPizza;
public PizzaDecorator(Pizza specialPizza) {
this.specialPizza = specialPizza;
}
@Override
public String makePizza() {
return specialPizza.makePizza();
}
}
4. Concrete Decorators (Toppings)
Each topping overrides the method, calls the underlying component, and chains its own topping enhancement:
public class ChickenPizzaDecorator extends PizzaDecorator {
public ChickenPizzaDecorator(Pizza specialPizza) {
super(specialPizza);
}
@Override
public String makePizza() {
return specialPizza.makePizza() + " + Spicy Chicken";
}
}
public class CheesePizzaDecorator extends PizzaDecorator {
public CheesePizzaDecorator(Pizza specialPizza) {
super(specialPizza);
}
@Override
public String makePizza() {
return specialPizza.makePizza() + " + Mozzarella Cheese";
}
}
Why Use the Decorator Pattern?
- Single Responsibility Principle: Keep individual feature enhancements isolated within dedicated decorator classes.
- Open/Closed Principle: Introduce new toppings or custom layers anytime without modifying existing base code.
- Runtime Composable: Chain decorators dynamically in any configuration or sequence.
Related Tutorials You Might Like
Check out these related design pattern tutorials from the channel:
Click here to watch in Youtube : https://www.youtube.com/watch?v=JXgEyF42jRE
Click the below Image to Enlarge
| Decorator Design pattern - Real Time Example [Pizza] |
See also:
No comments:
Post a Comment