🥞 Master Core Java & Structural Design Patterns!
Enjoying this hands-on breakdown? Subscribe to Ram N Java for clean code examples, software design principles, 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 or enhancements to an existing object dynamically at runtime without altering its original code.
Instead of relying on deep inheritance trees—which creates class explosion—this pattern uses object composition to wrap objects inside flexible decorators.
The Real-World Scenario: Decorating a Dosa
Consider ordering breakfast at an Indian restaurant. Everything begins with a standard Plain Dosa. From there, you might want delicious variations such as:
- Masala Dosa (Plain Dosa decorated with potato masala)
- Onion Dosa (Plain Dosa decorated with finely chopped onions)
Creating rigid sub-classes for every conceivable combination creates unnecessary complexity. With the Decorator Pattern, decorators wrap the base plain dosa to add masala or onions dynamically!
Step-by-Step Code Walkthrough
1. Component Interface
Define the core contract for making a dosa:
public interface Dosa {
String makeDosa();
}
2. Concrete Component
Implement the base plain dosa without any toppings:
public class PlainDosa implements Dosa {
@Override
public String makeDosa() {
return "Plain Dosa";
}
}
3. Abstract Decorator
The decorator class implements Dosa and holds a reference to a wrapped Dosa object:
public abstract class DosaDecorator implements Dosa {
protected Dosa dosa;
public DosaDecorator(Dosa dosa) {
this.dosa = dosa;
}
@Override
public String makeDosa() {
return dosa.makeDosa();
}
}
4. Concrete Decorators
Create specialized decorators for masala and onion toppings:
public class MasalDosaDecorator extends DosaDecorator {
public MasalDosaDecorator(Dosa dosa) {
super(dosa);
}
@Override
public String makeDosa() {
return dosa.makeDosa() + " + Masala added";
}
}
public class OnionDosaDecorator extends DosaDecorator {
public OnionDosaDecorator(Dosa dosa) {
super(dosa);
}
@Override
public String makeDosa() {
return dosa.makeDosa() + " + Onion added";
}
}
5. Decorator Client Test
public class DecoratorClient {
public static void main(String[] args) {
// Plain Dosa
Dosa plainDosa = new PlainDosa();
System.out.println(plainDosa.makeDosa());
// Onion Dosa
Dosa onionDosa = new OnionDosaDecorator(new PlainDosa());
System.out.println(onionDosa.makeDosa());
// Masala Dosa
Dosa masalDosa = new MasalDosaDecorator(new PlainDosa());
System.out.println(masalDosa.makeDosa());
}
}
Why Use the Decorator Pattern?
- Open/Closed Principle: Add new toppings easily without changing existing classes.
- Runtime Flexibility: Assemble and combine features on demand.
- Clean Modularity: Prevents massive, unmaintainable class hierarchies.
Related Tutorials You Might Like
Deepen your software engineering expertise with these design pattern tutorials:
Click here to watch in Youtube : https://www.youtube.com/watch?v=x5mIx0Wq-nI
| Decorator Design pattern - Implementation [Dosa] |
| Decorator Design pattern - Implementation [Dosa] - Class Diagram |
Dosa.java
No comments:
Post a Comment