Decorator design pattern is used to modify the functionality of an object at runtime. At the same time other instances of the same class will not be affected by this, so individual object gets the modified behavior. Decorator design pattern is one of the structural design pattern (such as Adapter Pattern, Bridge Pattern, Composite Pattern) and uses abstract classes or interface with composition to implement.
Table of Contents
Decorator Design Pattern
We use inheritance or composition to extend the behavior of an object but this is done at compile time and its applicable to all the instances of the class. We can’t add any new functionality of remove any existing behavior at runtime – this is when Decorator pattern comes into picture.
Suppose we want to implement different kinds of cars – we can create interface Car to define the assemble method and then we can have a Basic car, further more we can extend it to Sports car and Luxury Car. The implementation hierarchy will look like below image.
But if we want to get a car at runtime that has both the features of sports car and luxury car, then the implementation gets complex and if further more we want to specify which features should be added first, it gets even more complex. Now imagine if we have ten different kind of cars, the implementation logic using inheritance and composition will be impossible to manage. To solve this kind of programming situation, we apply decorator pattern in java.
We need to have following types to implement decorator design pattern.
- Component Interface – The interface or abstract class defining the methods that will be implemented. In our case
Car
will be the component interface.package com.journaldev.design.decorator; public interface Car { public void assemble(); }
- Component Implementation – The basic implementation of the component interface. We can have
BasicCar
class as our component implementation.package com.journaldev.design.decorator; public class BasicCar implements Car { @Override public void assemble() { System.out.print("Basic Car."); } }
- Decorator – Decorator class implements the component interface and it has a HAS-A relationship with the component interface. The component variable should be accessible to the child decorator classes, so we will make this variable protected.
package com.journaldev.design.decorator; public class CarDecorator implements Car { protected Car car; public CarDecorator(Car c){ this.car=c; } @Override public void assemble() { this.car.assemble(); } }
- Concrete Decorators – Extending the base decorator functionality and modifying the component behavior accordingly. We can have concrete decorator classes as
LuxuryCar
andSportsCar
.package com.journaldev.design.decorator; public class SportsCar extends CarDecorator { public SportsCar(Car c) { super(c); } @Override public void assemble(){ super.assemble(); System.out.print(" Adding features of Sports Car."); } }
package com.journaldev.design.decorator; public class LuxuryCar extends CarDecorator { public LuxuryCar(Car c) { super(c); } @Override public void assemble(){ super.assemble(); System.out.print(" Adding features of Luxury Car."); } }
Decorator Design Pattern – Class Diagram
Decorator Design Pattern Test Program
package com.journaldev.design.test;
import com.journaldev.design.decorator.BasicCar;
import com.journaldev.design.decorator.Car;
import com.journaldev.design.decorator.LuxuryCar;
import com.journaldev.design.decorator.SportsCar;
public class DecoratorPatternTest {
public static void main(String[] args) {
Car sportsCar = new SportsCar(new BasicCar());
sportsCar.assemble();
System.out.println("\n*****");
Car sportsLuxuryCar = new SportsCar(new LuxuryCar(new BasicCar()));
sportsLuxuryCar.assemble();
}
}
Notice that client program can create different kinds of Object at runtime and they can specify the order of execution too.
Output of above test program is:
Basic Car. Adding features of Sports Car.
*****
Basic Car. Adding features of Luxury Car. Adding features of Sports Car.
Decorator Design Pattern – Important Points
- Decorator design pattern is helpful in providing runtime modification abilities and hence more flexible. Its easy to maintain and extend when the number of choices are more.
- The disadvantage of decorator design pattern is that it uses a lot of similar kind of objects (decorators).
- Decorator pattern is used a lot in Java IO classes, such as FileReader, BufferedReader etc.
what is the user of CarDecorator. We can ignore this class and achieve the same output
I also didn’t understand this part. Why do we use CarDecorator ?
Great concise and very clear explanation. Thanks!
This is a great example, thank you.
If I may suggest, I believe it would be more didactic if you use Options instead of Cars for the Decorator related classes, this way it’s easier to understand that the final Car will be the assemble of different options (or features).
Another example
https://github.com/radhikapatel4391/CS680/tree/master/Homework3/src/hw3
Very nice tutorial point to point and simple easy to understand.
DVDPlayer example..
https://github.com/radhikapatel4391/CS680/tree/master/Homework3/src/hw3
Nice blog…
Very helpful information, I’m glad you shared it with people like us who are learning it
Hello,everyone! I have Monster(main class) and some Concrete classes(, like Troll,Vampire). Also I have MonsterDecorators,like Club,Sword and etc.
EXAMPLE:
Monster troll = new Troll();
troll.getAttackPower() // 30
troll.attack(); // The troll tries to grab you!
troll.fleeBattle(); // The troll shrieks in horror and runs away!
–>change the behavior of the simple troll by adding a decorator
troll = new ClubDecorator(troll);
troll.getAttackPower() // 42
troll.attack(); // The troll tries to grab you! The troll swings at you with a club!
troll.fleeBattle(); // The troll shrieks in horror and runs away! And loses his club while running!
so after fleeBattle method, how troll can be just Troll, without any decorators?
Not sure if it will work but it’s worth a try:
toll = new Troll();
or
Troll goodOldTroll = (Troll) troll;
Ah ha …. This is a Junit rule .
Statement.apply( (Statement) base )
.
ahh :(….. I havent been outside for a while
How to get the features of Luxury Car separately if I need them for another car at my home.
I assume the same scenario is for Dosa where you can get plain dosa, dosa with masala and dosa with chutney.
So masala and chutney classes extend DosaDecorator. PlainDosa class and DosaDecorator class implements Dosa interface.
Now what if i want extra chutney (means only chutney separately) ?
Thanks in advance.
Hi Arun,
Looks like with Decorator DP it is not possible to get extra chutney. You can’t ask for more aloo or chutney.
Actually chutney here is not a separate class, it is dependent on dosa interface. You will have to use some other DP.
But you brought the nice question over here. Were you able to figure out the answer to your problem?
It can be done by changing implementation of assemble method in CarDecorator a bit.
@Override
public void assemble() {
if(c != null) {
c.assemble();
}
}
And creating an object of Chutney as
Dosa chutney = new Chutney(null);
chutney.assemble();
@ArunSingh You asked solution for extra chutney. If you want double chutney with plain dosa then you use below code
Dosa dosa = new PlainDosa();
dosa = new Chutney(dosa);
dosa = new Chutney(dosa);
How to print only Luxury Car?
Thanks
new LuxuryCar(new BasicCar());
Hello. I used your tutorial to implement a Decorator, but found an error:
sportsLuxuryCar.assemble(); won’t execute the assemble() method for every Decorator used when creating the instance. So the output of sportsLuxuryCar.assemble(); wont’ be:
“Basic Car. Adding features of Luxury Car. Adding features of Sports Car.” but “Basic Car. Adding features of Sports Car.” instead.
I think you should correct that in the tutorial, because the chain execution of the assemble() method is useful and should be invoked in constructors in order to work.
Thank you!
I think CarDecorator should be an abstract class in order for it to confirm to decorator design pattern ,
The relationship between a car and the decorator is inheritance, doesn’t sound quite right to call a CarDecorator “is a” Car.
CarDecorator has to implement Car interface to provide methods to create Car objects. If you won’t implement Car interface then below code will start giving compile time error.
Here inheritance is not used in its usual type “is a ” . Here inheritance provides common supertype for car decorator and basic car.
Pankaj sir
multiple design pattern using create Framework?
example
login Framework
Not sure what you meant here.
I believe you should put “super.assemble();” instead of “car.assemble();” in concrete decorators.
But still your tutorial is great! Thank you very much!
Thanks for the input, yes you are right. I have corrected it.
You said: “Now image if we have ten different kind of cars, the implementation logic using inheritance and composition will be impossible to manage”
But then you still created 2 classes for each type of car (LuxuryCar & SportsCar). So the this pattern didn’t solve the problem of having ten different kind of cars.
Or what did I get wrong here ?
Thank you.
I believe you will need to use another pattern like the Factory pattern. One drawback to the decorator pattern is that it can add a lot of smaller classes and increase the complexity of the code.
Yes, this is the drawback of Decorator pattern, you will have a lot of similar classes.
The example with 2 classes helps to explain the concept, but in real life, in grosso modo, through n different decorator classes you can define n! different subclasses, it’s worth it
I want to ask you a question.How did you draw a class diagram?
which tool? Could you show some useful UML plugins for eclipse ?
Thank you.
I use ObjectAid UML Explorer for class diagram. It’s a simple tool and quick to install.
Thanks for the nice tutorial.