GoF Definition: Attach additional responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality.
This main principle of this pattern says that we cannot modify existing functionalities but we can extend them. In other words, this pattern is open for extension but closed for modification. The core concept applies when we want to add some specific functionalities to some specific object instead of to the whole class.
Suppose you already own a house. Now you have decided to add an additional floor. Obviously, you do not want to change the architecture of ground floor (or existing floors). You may want to change the design of the architecture for the newly added floor without affecting the existing architecture for existing floor(s).
Suppose in a GUI-based toolkit, we want to add some border properties. We can do this by inheritance. But it cannot be treated as the best solution because our user or client cannot have absolute control from the creation. The core of that choice is static there.
Decorator can offer us a more flexible approach: here we may surround the component in another object. The enclosing object is termed “decorator.” It conforms to the interface of the component it decorates. It forwards requests to the component. It can perform additional operations before or after those forwarding requests. An unlimited number of responsibilities can be added with this concept.
Please go through this example. Here we have not tried to modify the original doJob() method’s functionality. Two decorators, ConcreteDecoratorEx_1 and ConcreteDecoratorEx_2, are added here to enhance functionality, but the original doJob()’s working is not disturbed due to this addition.
High-level structure of the parts of the program is as follows:
package decorator.pattern.demo;
abstract class Component
{
public abstract void doJob();
}
class ConcreteComponent extends Component
{
@Override
public void doJob()
{
System.out.println(" I am from Concrete Component-I am closed for modification.");
}
}
abstract class AbstractDecorator extends Component
{
protected Component com ;
public void SetTheComponent(Component c)
{
com = c;
}
public void doJob()
{
if (com != null)
{
com.doJob();
}
}
}
class ConcreteDecoratorEx_1 extends AbstractDecorator
{
public void doJob()
{
super.doJob();
//Add additional thing if necessary
System.out.println("I am explicitly from Ex_1");
}
}
class ConcreteDecoratorEx_2 extends AbstractDecorator
{
public void doJob()
{
System.out.println(“”);
System.out.println("***START Ex-2***");
super.doJob();
//Add additional thing if necessary
System.out.println("Explicitly From DecoratorEx_2");
System.out.println("***END. EX-2***");
}
}
class DecoratorPatternEx
{
public static void main(String[] args)
{
System.out.println("***Decorator pattern Demo***");
ConcreteComponent cc = new ConcreteComponent();
ConcreteDecoratorEx_1 cd_1 = new ConcreteDecoratorEx_1();
// Decorating ConcreteComponent Object //cc with ConcreteDecoratorEx_1
cd_1.SetTheComponent(cc);
cd_1.doJob();
ConcreteDecoratorEx_2 cd_2= new ConcreteDecoratorEx_2();
// Decorating ConcreteComponent Object //cc with ConcreteDecoratorEx_1 & //ConcreteDecoratorEX_2
cd_2.SetTheComponent(cd_1);//Adding //results from cd_1 now
cd_2.doJob();
}
}
What are the main advantages of using decorator patterns?
How is this pattern different from inheritance?
We can add or remove responsibilities by simply attaching or detaching decorators. But with the simple inheritance technique, we need to create a new class for new responsibilities. So, there will be many classes inside the system, which in turn can make the system complex.
What is the major disadvantage of using this pattern?
First of all, if we are careful enough, there is no significant disadvantage. But if we create too many decorators in the system, the system will be hard to maintain and debug. At the same time, the decorators can create unnecessary confusion.