10/20/2005

Car Dealer sample - Decorator Pattern

Prev post

Decorator Pattern :

Intent from GoF : Attach additional responsibilities to an object dynamically. Decorators provide flexible alternative to subclassing for extending functionality.

Decorator pattern allows design to be flexible when there is a need to add responsibilities to an object at runtime, based on configuration or by someother means. The responsibilities could be anything such as, in the car dealer example, the car features will be added dynamically based on customer selection. The UML for decorator pattern is shown below.


The intent is to add features or responsibilities to the component. Each feature or responsibility will be created as a decorator class as shown. The decorator wraps the component class (check the constructor of decorator in UML) and adds the responsibility onto that component. This composition of component class into decorator makes Decorator pattern flexible enough to pass any component (even Decorators because, decorators are also components as they derive from it) and add features over feature over feature...

In car dealer sample, we faced the problem of numerous classes created when we designed car types and each car type supporting various car features. Check my previous post for more details on this. To solve the problem with decorator pattern, we are going to design the system as shown in the following UML diagram.




Above diagram shows 2 sides. One side we have all car types deriving from Car class, and another side car features deriving from a decorator class that intern derives from a Car. Observe that the Decorator class constructor takes in Car instance, which can be any Car ( car type instance or decorator instance too ). Now, lets consider how our design supports the functionality we need.

Our goal is to create a coupe that has All power options, Leather seat and moon roof ( and come what may..). Earlier we had used inheritance and defined a class AllPowerLeatherMoonRoofCoupe. But now, to get a car with such features what we need is this..

myCar = new AllPoweredDecorator( new LeatherDecorator( new MoonRoofDecorator( new Coupe() )));

Remember, the decorator wraps a car instance, that allows me to add one feature at a time to coupe. Similarly, i can add any number of features to any car type dynamically based on what customer selects, and the number of classes in design is small. Observe that car types are completely independent of car features. Adding a new car type or a new car feature does not effect the existing design or code.

So applying decorator pattern solved the problems like tremendously reduced number of classes, flexibility to add features dynamically (you can even add a feature twice to the component..cool haa), eases maintainance.

Few more Examples

1. System.IO namespace in .Net
this.Stream = new BufferredStream( new MemoryStream( new Stream() )));
2. In car dealer example, if we have to add color twice to the car
this.Car = new ColorCoatedDecorator( new ColorCoatedDecorator( new Sedan() )));

Next, we are going to design Car dealer example without and with Strategy Pattern, and observe the advantages. stay tuned.

Next post

1 Comments:

At 9:09 PM, Blogger Vijay said...

Good Job.

 

Post a Comment

Links to this post:

Create a Link

<< Home