Platinum Partner
java,computer science

Design Patterns Revisited - Decorator Pattern, Decorating your software

Here is a real life story; Years ago one of my colleagues and I developed a piece of software for order and payment management of restaurants. That time we did not know about how this process works, so we just role-played as a waiter, a restaurant owner and a customer. We made an assumption that a product's price is immutable if any change differenciates the price this should be a new product (like cheese added hamburger is cheeseburger). The changes which don't effect the price are stored as String field. In time, some restaurants started asking for products which can have extras, like pizza but with extra cheese. We kindly asked them to create new products from the admin console for those extras which change the price of the product. Where we failed was that we thought if the price changes there is no harm to create that as a new product, but imagine a pizza with combination of 20 different ingredients. Years after it is so easy to see why what we had failed. We needed to decorate the products instead of just adding a detailed text which can't update the price (just like we did).

The Decorator pattern is very easy to understand, use and implement. Lets imagine we have a car factory and we offer a variety of options to our customers - sunroof, airconditioner, airbags etc. First of all we need create our Car object. To make it simple I will be demonstrating a concrete car object but the best use should be creating a Car interface and build your Car objects implementing this interface.


public class FamilyCar{
private String description="This is family version 5 door";
private double price=10;
public String getDescription(){
return description;
}

public double getPrice(){
return price;
}
}

So far so good, but as our car hits the stores, customers would like options like sunroofs, extra airbags, child seat, a/c and we can't give those away for free. So lets create a decorator, again for ease of understanding I am creating a concrete decorator class, but in real life we should do that via interfaces for extensibility.

 

public class Sunroof{
private FamilyCar familyCar;
public Sunroof(FamilyCar familyCar){
this.familyCar=familyCar;
}
public String getDescription(){
return familyCar.getDescription()+" with sunroof";
}
public double getPrice(){
return familyCar.getPrice()+(familyCar.getPrice()*0.1);
}
}

So simply, if you want to sell a family car with sunroof, you can create a family car object and decorate it with sunroof, thats it. You may have noticed right now we can't handle to sell a car with sunroof and airbag (imagine we also have an airbag decorator) which is not good. So lets change our implementation...


public class FamilyCar implements Car{

...

public class Sunroof implements Car{

private Car car;

...

public class Airbag implements Car{

private Car car;

...

Now you can create a family car decorated with sunroof and airbag and the price will be calculated automatically.

new Airbag(new Sunroof(new FamilyCar())).getPrice();

 

You may have different interfaces for your Car and Option decorators and let your decorator interface extend your Car interface so you would have seperate implementations. Either way you choose, you will have vast variety of options to decorate your car and you will be the most extensible car dealer who can offer any price for any options wanted by their customers. Not bad? Let's burn some rubber and do not hesitate to use the decorators whenever you think they might work...

I really recommend you to read chapter 3 on Head First Design Patterns which I think has the best example for the topic.

{{ tag }}, {{tag}},

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}
{{ parent.authors[0].realName || parent.author}}

{{ parent.authors[0].tagline || parent.tagline }}

{{ parent.views }} ViewsClicks
Tweet

{{parent.nComments}}