Decorator Pattern: is a structural design pattern that lets you attach new behaviors to objects by placing these objects inside special wrapper objects that contain the behaviors.We don't need to subclass everything. Inheritance is extension at compile time. Using decorator pattern we can use extension at runtime using composition.Decorator pattern attached additional responsibilities to an object dynamically. It provides a flexible alternative to subclassing for extending functionality.
Problem Statement -
Suppose we have to design a pizza or coffee ordering system or website.
Here we do not know in advance what a customer would order. So we can't predict the behaviour at compile time.
Because the customer has many options to include toppings in pizza or codiments (cream, milk, sugar) in his coffee.
If we try to design this class structure using inheritance, then we might have tonnes of classes which would be a nightmare to maintain.
Also new types of toppings keep coming in the future, it would also be difficult to extend functionalities. So here decorator pattern comes to rescue.
Problems with subclassing or inheritance -
Inheritance is static. You can’t alter the behavior of an existing object at runtime. You can only replace the whole object with another one that’s created from a different subclass.
Subclasses can have just one parent class. In most languages, inheritance doesn’t let a class inherit behaviors of multiple classes at the same time.
Solution
One of the ways to overcome these problems is by using Aggregation or Composition instead of Inheritance
How Decorator Pattern works -
Here is the class diagram for pizza ordering system:-

How to Implement decorator pattern -
Create an interface.
Create concrete classes implementing the same interface.
Create an abstract decorator class implementing the above same interface.
Create a concrete decorator class extending the above abstract decorator class.
Now use the concrete decorator class created above to decorate interface objects.
Things to keep in mind:
We use inheritance here for Type Matching only not to get the behavior.
The behavior comes in through composition of decorators.
Decorators have the same supertype as the objects they decorate.
You can use one or more decorators to wrap an object.
Given that the decorator has the same supertype as the object it decorates, we can pass around a decorated object in place of the original (wrapped) object.
The decorator adds its own behavior either before and/or after delegating to the object it decorates to do the rest of the job.
Disadvantages of Decorator Pattern-
Decorators can complicate the process of instantiating the component because you not only have to instantiate the component but wrap it in a number of decorators
Decorators result in large number of small classes and it looks overwhelming like the java.io package.
Comments