🍕 Master Core Java & Structural Design Patterns!
Enjoying this hands-on breakdown? Subscribe to Ram N Java for clean code, design architecture, and real-world Java tutorials.
🔔 Subscribe to Ram N JavaUnderstanding the Decorator Design Pattern
The Decorator Pattern is a structural design pattern that lets you dynamically attach additional responsibilities or toppings to an object at runtime without altering its original source code.
Instead of building massive class inheritance hierarchies for every possible combination, decorators wrap the target component using object composition.
The Real-World Scenario: Decorating a Pizza
Consider ordering a pizza. Every customer starts with a standard base pizza (such as a Plain Pizza or simple crust). From there, toppings are added dynamically:
- Extra Cheese
- Chicken / Meat
- Vegetables
Creating subclasses for every combination—such as PlainPizzaWithCheeseAndChicken or PlainPizzaWithChickenOnly—leads to class explosion and rigid code.
With the Decorator Pattern, each topping acts as a wrapper that augments both description and price dynamically!
Step-by-Step Code Walkthrough
1. Component Interface
Define the core contract for preparing a pizza:
public interface Pizza {
String makePizza();
}
2. Concrete Component
Create a base pizza implementation:
public class PlainPizza implements Pizza {
@Override
public String makePizza() {
return "Plain Dough Pizza";
}
}
3. Abstract Decorator
The abstract decorator implements Pizza and maintains a reference to a wrapped 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)
Implement specific toppings that enhance the pizza:
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";
}
}
5. Execution Example
public class PizzaTest {
public static void main(String[] args) {
Pizza pizza = new CheesePizzaDecorator(new ChickenPizzaDecorator(new PlainPizza()));
System.out.println(pizza.makePizza());
// Output: Plain Dough Pizza + Spicy Chicken + Mozzarella Cheese
}
}
Why Use the Decorator Pattern?
- Open/Closed Principle: Introduce new toppings anytime without modifying existing pizza classes.
- Flexible Combination: Chain toppings dynamically in any desired order.
- Cleaner Code: Eliminates bloated inheritance hierarchies.
Related Tutorials You Might Like
Learn more about design patterns with these related lessons from the channel:
Click here to watch in Youtube : https://www.youtube.com/watch?v=Xz2eKQy9kBU
| Decorator Design pattern - Implementation [Pizza] |
| Decorator Design pattern - Implementation [Pizza] - Class Diagram |
Pizza.java
No comments:
Post a Comment