Decorator Design Pattern

The Decorator Design Pattern adds additional functionalities dynamically to an object. A decorator extends the responsibilities of a class by using composition not inheritance.

A decorator object contains an original object instance as member variable and it adds new functionalities either before or/and after delegating it to the original object. It comes under structural design pattern as it provides one of the best ways to extend the responsibilities of a class.

Advantages of Decorator Pattern

  • It allows classes to extend easily to support new requirements without modifying existing code.
  • A decorator implements the same interface as the object it decorates. We can use the decorator object(typecasted to supertype) where original object was expected.

When we should use Decorator Pattern

  • When we want to dynamically add or remove functionalities to a class without affecting the behaviour of other objects from the same class.
  • When we want to decouple Concrete implementations from responsibilities and behaviours.
  • We want to add additional functionalities to a class without affecting any of the clients.
  • When extending the functionalities of a class using inheritance will end up in creating lots of sub-classes.

Implementation of Decorator Design Pattern

In this example, we already have a PlainPizza class that implements Pizza interface. Now we want to add an extra functionality of adding extra cheese to pizza by keeping the interface same as Pizza.

We will first create an Pizza interface and it's concrete implementation PlainPizza.

Pizza.java
public interface Pizza {
    public float getPrice();
    public void preparePizza();
    public void packPizza();
}
PlainPizza.java
public class PlainPizza implements Pizza {
    @Override
    public float getPrice(){
        return 10;
    }
 
    @Override 
    public void preparePizza(){
        System.out.println("Prepairing Pizza");
    }
 
    @Override
    public void packPizza(){
        System.out.println("Packing Pizza");
    }
}

Create abstract PizzaDecorator class implementing the Pizza interface and concrete decorator class extending PizzaDecorator class. This will ensure that all decorator classes will have common Pizza interface.

PizzaDecorator.java
public class PizzaDecorator implements Pizza {
 
    protected Pizza pizza;
 
    public PizzaDecorator(Pizza pizza) {
        this.pizza = pizza;
    }
 
    public float getPrice(){
        return pizza.getPrice();
    }
 
    public void preparePizza(){
        pizza.preparePizza();
    }
 
    public void packPizza(){
        pizza.packPizza();
    }
}

CheeseBurstPizza.java class overrides the Pizza interface methods to provide additional functionalities or adding more cheese toppings.

CheeseBurstPizza.java
public class CheeseBurstPizza extends PizzaDecorator {
 
    public CheeseBurstPizza(Pizza pizza){
        super(pizza);
    }
 
    @Override
    public float getPrice(){
        // Extra money for Cheese Burst 
        return pizza.getPrice() + 5.0f;
    }
 
    @Override
    public void preparePizza(){
        System.out.println("Adding Extra Cheese..");
        pizza.preparePizza();
    }
 
    @Override
    public void packPizza(){
        pizza.packPizza();
    }
}

DecoratorPatternExample.java class creates a plane pizza and Cheese Burst Pizza using Pizza interface.

DecoratorPatternExample.java
public class DecoratorPatternExample {
  public static void main(String[] args) { 
      // Prepairing a Plain pizza
      Pizza plainPizza = new PlainPizza();
      plainPizza.preparePizza();
      plainPizza.packPizza();
      System.out.println(plainPizza.getPrice());
      System.out.println("---------------------------");
   
      // Prepairing a Cheese Burst Pizza using Pizza interface only
      Pizza cheeseBurstPizza = new CheeseBurstPizza(new PlainPizza());
      cheeseBurstPizza.preparePizza();
      cheeseBurstPizza.packPizza();
      System.out.println(cheeseBurstPizza.getPrice());
  }
}

Output

Prepairing Pizza
Packing Pizza
10.0
---------------------------
Adding Extra Cheese..
Prepairing Pizza
Packing Pizza
15.0

Related Topics
Strategy Design Pattern
Builder Design Pattern
Bridge Design Pattern
Memento Design Pattern
Mediator Design Pattern
Facade Design Pattern
Command Design Pattern
Interpreter Design Pattern
Observer Design Pattern
State Design Pattern
List of Design Patterns