Hello guys, if you want to learn about Decorator design pattern in Java then you are at the right place. I was thinking to write on decorator design pattern in Java when I first wrote 10 interview questions on Singleton Pattern in Java. Since design patterns are quite important while building software and it’s equally important on any Core Java Interview, It’s always good to have a clear understanding of various design patterns in Java. In this article, we will explore and learn the Decorator Design pattern in Java which is a prominent core Java design pattern and you can see a lot of its examples in JDK itself.
JDK use decorator pattern in IO package where it has decorated Reader and Writer Classes for the various scenario, for example, BufferedReader and BufferedWriter are examples of decorator design pattern in Java.
From design perspective it's also a good idea to learn how existing things work inside JDK itself for example How HashMap works in Java or How the SubString method work in Java, that will give you some idea of things you need to keep in mind while designing your Class or interface in Java. Now let’s Move on to the Decorator pattern in Java.
Btw, In order to best understand design patterns, you need to work out some scenarios, examples, etc. It's best to get this kind of knowledge as part of your work but even if you don't get there, you can supplement them by joining these Java design pattern courses and doing some object-oriented software design exercises.
From design perspective it's also a good idea to learn how existing things work inside JDK itself for example How HashMap works in Java or How the SubString method work in Java, that will give you some idea of things you need to keep in mind while designing your Class or interface in Java. Now let’s Move on to the Decorator pattern in Java.
Btw, In order to best understand design patterns, you need to work out some scenarios, examples, etc. It's best to get this kind of knowledge as part of your work but even if you don't get there, you can supplement them by joining these Java design pattern courses and doing some object-oriented software design exercises.
Decorator Design Pattern in Java
In this Java tutorial we will see:
- What is the decorator pattern in Java?
- When to use decorator pattern in Java?
- How to use decorator pattern in Java?
- Example of decorator design pattern
- Advantage and Disadvantage of decorator pattern in Java
What is a decorator design pattern in Java?
· Decorator design pattern is used to enhance the functionality of a particular object at run-time or dynamically.
· At the same time other instance of same class will not be affected by this so individual object gets the new behavior.
· Basically we wrap the original object through decorator object.
· Decorator design pattern is based on abstract classes and we derive concrete implementation from that classes,
· It’s a structural design pattern and most widely used.
I prefer to answer What is decorator design pattern in point format just to stress on important point like this pattern operator at individual object level. This question also asked in many Core Java interviews in Investment banks
What Problem is Solved by Decorator design Pattern?
Now the question is why this pattern has came into existence what is the problem with existing system which needs to be solved? so the answer is if anyone wants to add some functionality to an individual object or change the state of a particular object at run time it is not possible.
What is possible is that we can provide the specific behavior to all the object of that class at design time by the help of inheritance or using subclass, but Decorator pattern makes possible that we provide individual object of same class a specific behavior or state at run time. This doesn’t affect other object of same Class in Java.
When to use Decorator pattern in Java
When sub classing is become impractical and we need large number of different possibilities to make independent object or we can say we have number of combination for an object.
Secondly when we want to add functionality to individual object not to all object at run-time we use decorator design pattern.
Code Example of decorator design pattern:
To better understand concept of decorator design pattern let see a code example using Decorator Pattern in Java. You can also look inside JDK and find what are classes and packages which are using decorator pattern.
// Component on Decorator design pattern
public abstract class Currency {
String description = "Unknown currency";
String description = "Unknown currency";
public String getCurrencyDescription() {
return description;
}
return description;
}
public abstract double cost(double value);
}
// Concrete Component
public class Rupee extends Currency {
double value;
public Rupee() {
description = "indian rupees";
}
description = "indian rupees";
}
public double cost(double v){
value=v;
value=v;
return value;
}
}
}
//Another Concrete Component
public class Dollar extends Currency{
double value;
public Dollar () {
description = "Dollar”;
}
description = "Dollar”;
}
public double cost(double v){
value=v;
return value;
}
}
// Decorator
public abstract class Decorator extends Currency{
public abstract String getDescription();
}
// Concrete Decorator
public class USDDecorator extends Decorator{
Currency currency;
public USDDecorator(Currency currency){
this.currency = currency;
}
this.currency = currency;
}
public String getDescription(){
return currency.getDescription()+" ,its US Dollar";
}
return currency.getDescription()+" ,its US Dollar";
}
}
//Another Concrete Decorator
public class SGDDecorator extends Decorator{
Currency currency;
Currency currency;
public SGDDecorator(Currency currency){
this.currency = currency;
}
this.currency = currency;
}
public String getDescription(){
return currency.getDescription()+" ,its singapore Dollar";
}
return currency.getDescription()+" ,its singapore Dollar";
}
}
Now its time to check currency.
public class CurrencyCheck {
public static void main(String[] args) {
// without adding decorators
Currency curr = new Dollar();
System.out.println(curr.getDescription() +" dollar. "+curr.cost(2.0));
//adding decorators
Currency curr2 = new USDDecorator(new Dollar());
System.out.println(curr2.getDescription() +" dollar. "+curr2.cost(4.0));
Currency curr3 = new SGDDecorator(new Dollar());
System.out.println(curr3.getDescription() +" dollar. "+curr3.cost(4.0));
}
Explanation of the code:
We can understand this in the following terms:
1. Component Interface: In our example Currency interface is a component which used on its own or we need a decorator for that.
2. Concrete Component: it implements the Component and we add new behavior to this object dynamically. Dollar and Rupee are the concrete implementations of currency.
3. Decorator: Decorator contains a HAS a Relationship in simple word we can say it has an instance variable that holds a reference for the component they implement the same component which they are going to decorate. Here a Decorator is an abstract class that extends the currency.
4. Concrete Decorator: it’s an implementation of Decorator So USD Dollar and SGD Dollar are the implementation of Decorator contains instance variable for component interface or the thing which they are going to decorate.
Here is a nice UML diagram from Design Pattern in Java:
Advantage of Decorator design Pattern in Java
1.Decorator Pattern is flexible than inheritance because inheritance add responsibilities at compile time and it will add at run-time.
2. Decorator pattern enhance or modify the object functionality
Disadvantages of Decorator Pattern
The main disadvantage of using Decorator Pattern in Java is that the code maintenance can be a problem as it provides a lot of similar kinds of small objects (each decorator).
That’s all on decorator design pattern in Java. To get mastery on decorator patterns I suggest looking inside JDK library itself and finding what classes are decorated, why they are decorated. Also, think of a scenario where inheritance is impractical and you look more flexible and try to use decorator patterns in Java there.
Some more Interesting tutorials:
How to override equals method in Java
How to implement Thread in Java ? Example of Runnable interface
Difference between ConcurrentHashMap and Collections.synchronized maps and Hashtable in Java
Advanced concept on Enum in Java with Example
How to implement Thread in Java ? Example of Runnable interface
Difference between ConcurrentHashMap and Collections.synchronized maps and Hashtable in Java
Advanced concept on Enum in Java with Example
A Comprehensive coverage of the Decorator Pattern Javin..
ReplyDeleteSome general interview questions on J2EE Design patterns as a whole can be found by Clicking Here
Anand
Decorator has been used by JDK itself including I/O and collection classes.
ReplyDeleteRead more design patterns for interview:
Choosing Design Patterns for interview
decorator design pattern was tricky for me, I never really found where to use decorators. I knew it was used in Java IO package but except that I don't really find any other use of decorator pattern. is there any specific guideline or point exist which helps to decide whether to use decorator pattern or not ?
ReplyDeleteI have written the following example :
ReplyDeleteAbstrac Component :HouseComponent
Concrete Component Class :OneBedRoomHouse
Abstract Decorator :AbstractHouseDecorator
Concrete Decorator Class :OneBedRoomHouseWithCarSpaceDecorator
Concrete Decorator Class2 : OneBedRoomHouseWithSwimmingPoolDecorator
Decorator Test class : DecoratorDemo
=============================================
Abstract Component :
****************************
package com.patterns.decorator;
//This class will act as Component
public abstract class HouseComponent {
public String description=" Unknown House ";
public String getHouseDescription(){
return description;
}
public abstract Double getPrice();
}
-------------------------
Concrete Component:
****************************
package com.patterns.decorator;
public class OneBedRoomHouse extends HouseComponent{
public OneBedRoomHouse() {
description="1 BHK";
}
@Override
public Double getPrice() {
return 300000.00;
}
}
=======================
Abstract Decorator:
****************************
package com.patterns.decorator;
public abstract class AbstractHouseDecorator extends HouseComponent{
public abstract String getHouseDescription();
}
===================
Concrete Decorator class:
****************************
package com.patterns.decorator;
public class OneBedRoomHouseWithCarSpaceDecorator extends AbstractHouseDecorator{
public HouseComponent house;
public OneBedRoomHouseWithCarSpaceDecorator(HouseComponent house) {
this.house=house;
}
@Override
public String getHouseDescription() {
return house.getHouseDescription()+" with one car space";
}
@Override
public Double getPrice() {
Double modifiedPrice = house.getPrice() + house.getPrice() * .10;
return modifiedPrice;
}
}
--------------------------
concrete Decorator Class2:
****************************
package com.patterns.decorator;
public class OneBedRoomHouseWithSwimmingPoolDecorator extends
AbstractHouseDecorator {
public HouseComponent house;
public OneBedRoomHouseWithSwimmingPoolDecorator(HouseComponent house) {
this.house = house;
}
@Override
public String getHouseDescription() {
return house.getHouseDescription() + " and with swimmmingPool";
}
@Override
public Double getPrice() {
Double modifiedPrice = house.getPrice() + house.getPrice() * .25;
return modifiedPrice;
}
}
--------------------------------
Decorator Demo class:
****************************
package com.patterns.decorator;
public class DecoratorDemo {
public static void main(String[] args) {
HouseComponent oneBHKhouse = new OneBedRoomHouse();
System.out.println(oneBHKhouse.getHouseDescription()+", Price: "+oneBHKhouse.getPrice());
HouseComponent decoratedHouse1 = new OneBedRoomHouseWithCarSpaceDecorator(new OneBedRoomHouse());
System.out.println(decoratedHouse1.getHouseDescription()+", Price :"+decoratedHouse1.getPrice());
HouseComponent decoratedHouse2 =new OneBedRoomHouseWithSwimmingPoolDecorator(new OneBedRoomHouseWithCarSpaceDecorator(new OneBedRoomHouse()));
System.out.println(decoratedHouse2.getHouseDescription()+", Price :"+decoratedHouse2.getPrice());
}
}
-----------------------------------
output:
1 BHK, Price: 300000.0
1 BHK with one car space, Price :330000.0
1 BHK with one car space and with swimmmingPool, Price :412500.0
In above code example, we have mention below code.
ReplyDeletepublic String getDescription(){
return currency.getDescription()+" ,its US Dollar";
}
I see an error here that below line of code
return currency.getDescription()+" ,its US
should be replaced by
return currency.getCurrencyDescription()+" ,its US
SGDDecorator and USDDecorator doesn't implement the abstract methods it inherits. This code just will not compile as is.
ReplyDeleteI like the naming convention, having Decorator in the name of class, goes naming convention best practices, mentioned in Clean Code. By reading Decorator, any Java developer can recognize use of Decorator pattern.
ReplyDeleteSGDDecorator and USDDecorator doesn't implement the abstract methods it inherits. This code just will not compile as is.
ReplyDeletePlease don't post examples that don't work
I agree that Decorator is one of the most useful design pattern in object oriented language, not just java. I would like to add few key things, which I feel important to understand Decorator design pattern :
ReplyDelete- Decorator objects are part of same type hierarchy, they are decorating. For example if you are decorating Pizza then decorators like CanadianPizza, ItalianPizza or even IndianPizza will be part of same type hierarchy, either by implementing Pizza interface or extending Pizza class. This is important so that you can pass Decorator, where any method expect original object.
- You can apply more than one Decorator on Single object e.g. You can decorate your Coffee with Cream, Sugar or Milk. remember each of these decorator must be part of same type hierarchy.
- Decorator adds new behavior either before or after delegating request to the object it is decorating. For example, if we need to calculate cost of Coffe, which is decorated by Sugar and Cream than it will start from last decorator which is Cream, which delegates to Sugar, which finally delegates to Coffee, which return cost and then they add on top of that.
Beauty of this design pattern is that, it does all things at runtime, which means you have lot of flexibility on decorating your object.
Please verify and let me know if my corrections for the programs described are correct or not...
ReplyDeletepackage com.decorator;
public abstract class Currency {
String description = "Unknown currency";
public String getDescription() {
return description;
}
public abstract double cost(double value);
}
package com.decorator;
public class Rupee extends Currency {
double value;
public Rupee() {
description = "Indian Rupee";
}
@Override
public double cost(double v) {
value = v;
return value;
}
}
package com.decorator;
public class Dollar extends Currency {
double value;
public Dollar() {
description = "Dollar";
}
@Override
public double cost(double v) {
value = v;
return value;
}
}
package com.decorator;
public abstract class Decorator extends Currency {
public abstract String getDescription();
}
package com.decorator;
public class USDDecorator extends Decorator {
Currency currency;
public USDDecorator(Currency currency) {
this.currency = currency;
}
@Override
public String getDescription() {
return currency.getDescription()+" ,its US Dollar";
}
@Override
public double cost(double value) {
// TODO Auto-generated method stub
return currency.cost(value);
}
}
package com.decorator;
public class SGDDecorator extends Decorator {
Currency currency;
public SGDDecorator(Currency currency) {
this.currency = currency;
}
public String getDescription() {
return currency.getDescription() + " ,its singapore Dollar";
}
@Override
public double cost(double value) {
// TODO Auto-generated method stub
return currency.cost(value);
}
}
package com.decorator;
public class CurrencyCheck {
public static void main(String[] args) {
// without adding decorators
Currency curr = new Dollar();
System.out.println(curr.getDescription() + " dollar. " +curr.cost(2.0));
// adding decorators
Currency curr2 = new USDDecorator(new Dollar());
System.out.println(curr2.getDescription() + " dollar. "+curr2.cost(4.0));
Currency curr3 = new SGDDecorator(new Dollar());
System.out.println(curr3.getDescription() + " dollar. "+curr3.cost(4.0));
}
}
Output
--------------
Dollar dollar. 2.0
Dollar ,its US Dollar dollar. 4.0
Dollar ,its singapore Dollar dollar. 4.0
Please comment.
"1. Component Interface: In our example Currency interface is component which used on its own or we need decorator for that."
ReplyDelete********************************************************************************************
In your example, Component is an abstract class and not an interface.
The blog here does not mention at all, why inheritance cannot do the same thing as the decorator design pattern.
ReplyDeleteWith inheritance you can simply create the classes with extra functionality like USD and SGD (extending the Dollar class) and assign them at runtime to individual objects requiring extra functionality and for those which do not require extra functionality you can assign the Dollar object at runtime.
On the other side, with decorator design pattern too just like inheritance you have to code the concrete decorator classes at design time.
So there is nothing special there. Inheritance does all the things that the decorator design pattern does as far as this blog is concerned.
In order to truly understand why decorator design pattern is better than inheritance, please read the following article: https://dzone.com/articles/is-inheritance-dead