DEV Community

Priyank Bhardwaj
Priyank Bhardwaj

Posted on

Decorator Design Pattern: Adding Flexibility Without Changing Code!

What is decorator design pattern?

The Decorator Pattern is a structural design pattern that allows you to add new functionality to an existing object dynamically, without altering its structure. It’s a flexible alternative to subclassing.

Think of it as wrapping an object to enhance or modify its behavior.

Real-Life Example

Imagine a coffee shop:

  • A basic coffee costs ₹50.
  • You can add milk, sugar, or whipped cream as extra toppings.
  • Each topping adds to the cost without changing the base coffee class.

Java Implementation

Create a Coffee interface

public interface Coffee {
    double getCost();
    String getDescription();
}

Enter fullscreen mode Exit fullscreen mode

Implement a basic coffee

public class SimpleCoffee implements Coffee {

    @Override
    public double getCost() {
        return 50.0;
    }

    @Override
    public String getDescription() {
        return "Simple Coffee";
    }
}
Enter fullscreen mode Exit fullscreen mode

Create an abstract decorator

public abstract class CoffeeDecorator implements Coffee {
    protected Coffee decoratedCoffee;

    public CoffeeDecorator(Coffee coffee) {
        this.decoratedCoffee = coffee;
    }

    public double getCost() {
        return decoratedCoffee.getCost();
    }

    public String getDescription() {
        return decoratedCoffee.getDescription();
    }
}
Enter fullscreen mode Exit fullscreen mode

Add concrete decorators

public class MilkDecorator extends CoffeeDecorator {

    public MilkDecorator(Coffee coffee) {
        super(coffee);
    }

    @Override
    public double getCost() {
        return super.getCost() + 20.0;
    }

    @Override
    public String getDescription() {
        return super.getDescription() + ", Milk";
    }
}

public class SugarDecorator extends CoffeeDecorator {

    public SugarDecorator(Coffee coffee) {
        super(coffee);
    }

    @Override
    public double getCost() {
        return super.getCost() + 10.0;
    }

    @Override
    public String getDescription() {
        return super.getDescription() + ", Sugar";
    }
}
Enter fullscreen mode Exit fullscreen mode

Client class: Using the decorators

public class Main {
    public static void main(String[] args) {
        Coffee coffee = new SimpleCoffee();
        System.out.println(coffee.getDescription() + " ₹ " + coffee.getCost());

        // Add Milk
        coffee = new MilkDecorator(coffee);
        System.out.println(coffee.getDescription() + " ₹ " + coffee.getCost());

        // Add Sugar
        coffee = new SugarDecorator(coffee);
        System.out.println(coffee.getDescription() + " ₹ " + coffee.getCost());
    }
}
Enter fullscreen mode Exit fullscreen mode

Output

Simple Coffee ₹ 50.0
Simple Coffee, Milk ₹ 70.0
Simple Coffee, Milk, Sugar ₹ 80.0
Enter fullscreen mode Exit fullscreen mode

Key Takeaways

  • Decorator allows behavior to be added dynamically.
  • Open/Closed Principle: You can extend functionality without modifying existing code.
  • Avoid creating complex inheritance trees for every combination of features.

Pros:

  • More flexible than static inheritance.
  • Can combine multiple decorators at runtime.
  • Encourages composition over inheritance.

Cons:

  • Can become complex with many decorators.
  • Debugging may be harder due to nested wrappers.

When to Use Decorator Pattern

  • When you want to add responsibilities to objects dynamically.
  • When subclassing would result in too many classes.
  • When you want to avoid modifying the original object’s code.

Summary

The Decorator Pattern is perfect when you need flexible, runtime-added behavior for objects. In our coffee example, toppings could be added in any order without touching the base coffee class.


This is Part 8 of the Java Design Patterns Series.

If you find it insightful, please share your feedback. Also let me know if you have used decorator pattern in your projects.

Next Up: Composite Design Patterns!

Top comments (0)