Decorator Design Pattern
Saji Kuttan
Senior Software Engineer @HCL TECH | Ex-Infoscion | Building Secure and Scalable Software Applications | Full Stack Developer
The Decorator Design Pattern is a structural pattern that allows behavior to be added to individual objects, dynamically, without affecting the behavior of other objects from the same class. This is particularly useful for adding responsibilities to objects without modifying their code.
Ice Cream Example with Decorator Design Pattern
Imagine an ice cream shop where customers can start with a basic ice cream cone and then add scoops of different flavors like chocolate, mango, or vanilla. Each scoop adds a new flavor and cost to the basic ice cream. The Decorator Pattern is perfect for this scenario because it allows us to "decorate" the basic ice cream with additional flavors in a flexible manner.
Key Components of the Decorator Pattern:
Example:
Let's break it down in code:
Step 1: Define the IceCream interface
// The Component interface
public interface IceCream {
String getDescription();
double getCost();
}
Step 2: Create the BasicIceCream Concrete Component
// The Concrete Component
public class BasicIceCream implements IceCream {
@Override
public String getDescription() {
return "Basic Ice Cream";
}
@Override
public double getCost() {
return 1.00; // Base cost of the ice cream
}
}
Step 3: Create the IceCreamDecorator Abstract Decorator
// The Decorator class
public abstract class IceCreamDecorator implements IceCream {
protected IceCream iceCream;
public IceCreamDecorator(IceCream iceCream) {
this.iceCream = iceCream;
}
@Override
public String getDescription() {
return iceCream.getDescription();
}
@Override
public double getCost() {
return iceCream.getCost();
}
}
Step 4: Create Concrete Decorators for Different Scoops
// Chocolate Scoop Decorator
public class ChocolateScoop extends IceCreamDecorator {
public ChocolateScoop(IceCream iceCream) {
super(iceCream);
}
@Override
public String getDescription() {
return iceCream.getDescription() + ", Chocolate Scoop";
}
@Override
public double getCost() {
return iceCream.getCost() + 0.75; // Cost of a chocolate scoop
}
领英推荐
}
// Mango Scoop Decorator
public class MangoScoop extends IceCreamDecorator {
public MangoScoop(IceCream iceCream) {
super(iceCream);
}
@Override
public String getDescription() {
return iceCream.getDescription() + ", Mango Scoop";
}
@Override
public double getCost() {
return iceCream.getCost() + 0.80; // Cost of a mango scoop
}
}
// Vanilla Scoop Decorator
public class VanillaScoop extends IceCreamDecorator {
public VanillaScoop(IceCream iceCream) {
super(iceCream);
}
@Override
public String getDescription() {
return iceCream.getDescription() + ", Vanilla Scoop";
}
@Override
public double getCost() {
return iceCream.getCost() + 0.70; // Cost of a vanilla scoop
}
}
Step 5: Demonstrate the Ice Cream Decoration
public class Main {
public static void main(String[] args) {
// Start with a basic ice cream
IceCream iceCream = new BasicIceCream();
// Add a chocolate scoop
iceCream = new ChocolateScoop(iceCream);
// Add a mango scoop
iceCream = new MangoScoop(iceCream);
// Add a vanilla scoop
iceCream = new VanillaScoop(iceCream);
// Output the final ice cream description and cost
System.out.println("Description: " + iceCream.getDescription());
System.out.println("Cost: $" + iceCream.getCost());
}
}
Output:
Description: Basic Ice Cream, Chocolate Scoop, Mango Scoop, Vanilla Scoop
Cost: $3.25
Explanation:
Advantages:
Conclusion:
The Decorator Design Pattern provides a powerful way to extend the functionality of objects in a flexible and reusable manner. In our ice cream example, we can dynamically add different scoops to a basic ice cream, building complex combinations without altering the core class structure. This pattern is especially useful when you need to add responsibilities to objects without affecting others.
#SoftwareDesign #DecoratorDesign #Pattern #Architecture #DesignPatterns #Developers #ProgrammingTips