Tuesday, 20 May 2008

Design Patterns Revisited (2)- Decorator Pattern, Decorating your software

The decorator pattern is the second most used pattern for me after singletons. I really recommend you to read chapter 3 on Head First Design Patterns which I think has the best example for the topic.
Here is a real life story; Several years ago one of my colleague and I developed a software for Order and Payment management of Restaurants. That time we had concrete product objects with price property. In time some restaurants started asking for products which can have extras like pizza but with extra cheese or kebap but with yoghurt. We asked them to create new products from back office for that extras which changes price of the product. What we failed was 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.
Long years after it is so easy to see what we had failed. We needed to decorate the products instead of just adding a detail text which can't update the price (just like we did).
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 like, 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 built 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 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 simple, you want to sell a family car with sunroof, create a family car object and decorate it with sunroff, thats it. You may have notice right now we cant handle to sell a car with sunroff 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 would 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 to extend your car interface so you would 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? lets burn some rubber and do not hesitate to use the decorators whenever you think they might work...