Advantage of Decorator Design Pattern

Decorator design pattern modifies behavior of an object during runtime. At the same time other instances of the same class will not be affected by this, only individual objects will get modified behavior(added by Decorator classes). Decorator pattern uses abstract classes or interface with composition to implement.

Generally to add functionality to an existing object, inheritance or composition can be used. But disadvantage is that would be Compile time decision.This compile time decision, has a number of drawbacks, as specified below.

Suppose you have a Car class. Then in some place you want a Car with air bags, so you subclass Car and create AirbagCar class. And in some other place you want a tube less tyres for the Car. So you subclass again and create TubelessTyresCar. Well, now in some place you want tube less tyres and air bags both. None of the previous two sub classes have both capability. So you need to create a 3rd one. When creating a AirbagTubelessTyreCar you are actually duplicating the effort. You don’t need this class if you have any way to compose the capability of previous two. Well, things can go worse and these may lead to unnecessary class explosion.

Basically, by using decorator pattern you can add any number of additional responsibility to object at runtime which you cannot achieve by subclassing without potentially damaging your code structure.

The decorator pattern can be used to make it possible to extend (decorate) the functionality of a certain object at runtime.

Purpose of decorator pattern is to dynamically add additional behaviour/functionality, which is of course not possible at design time.

The decorator pattern is an alternative to subclassing. Subclassing adds behavior at compile time, and the change affects all instances of the original class; decorating can provide new behavior at runtime for individual objects.

Below is an example of Decorator Design Pattern

public interface Car{
public String driveCar();
}
public class SimpleCar implements Car {

  @Override
  public String driveCar() {
    return "drive SimpleCar";
  }

}

Below is decorator class, which is core of decorator design pattern. Instance is assigned dynamically at the creation of decorator using its constructor. Once assigned that instance method will be invoked.

abstract class CarDecorator implements Car {

  protected Car specialCar;

  public CarDecorator(Car specialCar) {
    this.specialCar = specialCar;
  }

  public String driveCar() {
    return specialCar.driveCar();
  }
}

public class AirbagCarDecorator extends CarDecorator {

  public AirbagCarDecorator(Car specialCar) {
    super(specialCar);
  }

  public String driveCar() {
    return specialCar.driveCar() + addAirbags();
  }

  private String addAirbags() {
    return " with Air bags, ";
  }
}

public class TubelessCarDecorator extends CarDecorator {

  public TubelessCarDecorator(Car specialCar) {
    super(specialCar);
  }

  public String driveCar() {
    return specialCar.driveCar() + addTubeless();
  }

  private String addTubeless() {
    return " with Air bags, ";
  }
}

public class MyDemo{
  public static void main(String args[])
  {
   SimpleCar obj =new TubelessCarDecorator(new AirbagCarDecorator(new SimpleCar()));
   System.out.println(obj.driveCar());
  }
}

In java.io package Decorator pattern has been widely used, as shown below
#1.java.io.BufferedReader;
java.io.FileReader;
java.io.Reader;
#2.java.io.SequenceInputStream
java.io.FileInputStream
java.io.InputStream
java.io.DataInputStream

You may also like to read:
How to Control maximum number of objects
How to combine two or more InputStreams into single InputStream
Design Pattern used for JDBC