Decorator pattern adds additional features to an existing object dynamically. In this post, I will use a simple example – decorate your girlfriend – to illustrate how decorator pattern works.
1. Decorator Pattern Story
Let’s assume you are looking for a girlfriend. There are girls from different countries such as America, China, Japan, France, etc. They may have different personalities and hobbies. In a dating web like eharmony.com, if each type of girl is an individual Java class, there would be thousands of classes. That is a serious problem called class explosion. Moreover, this design is not extensible. Whenever there is a new girl type, a new class needs to be created.
Let’s change the design, and let each hobby/personality becomes a decorator which can be dynamically applied to a girl.
2. Class Diagram
Girl is the abstract class at the top level, we have girls from different countries. With a GirlDecorator class, we can decorator each girl with any feature by adding a new decorator.
3. Decorator pattern Java code
Girl.java
public abstract class Girl { String description = "no particular"; public String getDescription(){ return description; } } |
AmericanGirl.java
public class AmericanGirl extends Girl { public AmericanGirl(){ description = "+American"; } } |
EuropeanGirl.java
public class EuropeanGirl extends Girl { public EuropeanGirl() { description = "+European"; } } |
GirlDecorator.java
public abstract class GirlDecorator extends Girl { public abstract String getDescription(); } |
Science.java
public class Science extends GirlDecorator { private Girl girl; public Science(Girl g) { girl = g; } @Override public String getDescription() { return girl.getDescription() + "+Like Science"; } public void caltulateStuff() { System.out.println("scientific calculation!"); } } |
We can add more method like “Dance()” to each decorator without any limitations.
Art.java
public class Art extends GirlDecorator { private Girl girl; public Art(Girl g) { girl = g; } @Override public String getDescription() { return girl.getDescription() + "+Like Art"; } public void draw() { System.out.println("draw pictures!"); } } |
Main.java
package designpatterns.decorator; public class Main { public static void main(String[] args) { Girl g1 = new AmericanGirl(); System.out.println(g1.getDescription()); Science g2 = new Science(g1); System.out.println(g2.getDescription()); Art g3 = new Art(g2); System.out.println(g3.getDescription()); } } |
Output:
+American
+American+Like Science
+American+Like Science+Like Art
We can also do something like this:
Girl g = new Science(new Art(new AmericanGirl())); |
4. Decorator Pattern Used in Java Stand Library
A typical usage of Decorator pattern is Java IO classes.
Here is a simple example –
BufferedReader input = new BufferedReader(new InputStreamReader(System.in)); //System.in is an InputStream object |
I agree
I think you could have chosen another example. This is a really good website, however, you really don’t need such an example to make your point. Maybe the predominantly male software engineers do not find this offensive ( and understandably so). As a woman who is also a software engineer, I find this objectifying women in general(unnecessary, because I understood Decorator just as well without the need to ‘decorate’ a girlfriend). Maybe some men might find my comment unnecessary, but in a field that already has such a low female population, I think we need to stop alienating women by creating such examples (which are not only unrelatable, but also offensive). I would really appreciate you changing this example.
http://www.codeproject.com/Tips/468951/Decorator-Design-Pattern-in-Java this is a better example
This is so sexist..you could have chosen a better example.
Yes. I think they can. If science and art extend girl directly and they compose a girl instance and a call to science [should delegate to the composed girl instance + extra functionality]
To your argument
For example girl2 might have feature one and feature two, girl 3 has feature 4 and 5. Without decorator pattern, you need to create more subclasses.
Let’s say there were 100 features, you could still have 100 subclasses. And if you wanted a combination of feature 1, 2,3 then you can still live with the 100 classes(not create any new classes ) . Feature1 can compose feature 2 (as a girl) which can compose feature3(as a girl).
This brings me to ask the question again.
Do we really need the abstract decorator or can we live with implementing the features as subclasses which compose a girl.
In my humble opinion, latter seems to be OK.
Do you think that we still need the abstract decorator?
Doing so can result in class explosion. What if the girl has 8 other features,and this 8 other features is needed on other area, and must have certain combinations. For example girl2 might have feature one and feature two, girl 3 has feature 4 and 5. Without decorator pattern, you need to create more subclasses. What if you have 100 features that has various combinations. Then you will need to create more subclassess. This will be a nightmare.
I don’t know why we need GirlDecorator? Can Class Science and Art extend from Girl directly?
agree with other guys, girl.java should be better to be replaced with an interface but an abstract class
I don’t understand why should the GirlDecorator extend the Girl Class, the GirlDecorator is not a Girl at all. It’s IMHO anti-pattern.
If you just want to have the Descprition method, you should implement an interface.
I’m not sure if this is the best example..at the end of the main, our girl like both Science and Art, but she cannot calculateStuff, only to draw (because g3 IS-A Art).. She could calculate but not to draw if the order would have be the opposite…I’m not saying this is neccesarily “wrong”, but it doesn’t feel right either.
I really think that the coffe example of the wikipedia (the second one in the page) is much better.
Shouldnt the Girl.java class be actually an interface and not abstract. Anyways there are no abstract methods defined
Hi,
Sometimes you read concepts all over the net with “intuitive”,”real-life” examples. Not all examples work for everyone. This one worked for me – had a light bulb glowing above my head. Thanx for this post and keep posting.
How to “new” ? ! ! !
Should not be caltulateStuff but calculateStuff 🙂