Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Alternatives to decorator pattern

I find decorator pattern to be most confusing. Please consider the example provided in "Head first design patterns book".

alt text

So to get a DarkRoast with double mocha and a whip, you have to write

Beverage beverage2 = new DarkRoast();
beverage2 = new Mocha(beverage2);                                       
beverage2 = new Mocha(beverage2);                                       
beverage2 = new Whip(beverage2); 

I feel this is unnecessary. Here is my implementation,

interface Beverage
{
   int Cost();
}

class DarkRoast : Beverage
{
   /* .... */
}

class Mocha : Beverage
{
   /* .... */
}

class Whip : Beverage
{
   /* .... */
}

// here is the changed part
class Order
{
    List<Beverage> beverages = new List<Beverage> beverages();
    public void AddItem(Beverage b)
    {
        beverages.Add(b);
    }

    public int Cost()
    {
        int cost;
        foreach(Beverage b in beverages)
            cost += b.Cost();
    }
}

// use it like
Order order = new Order();
order.AddItem(new DarkRoast());
order.AddItem(new Mocha());
order.AddItem(new Mocha());
order.AddItem(new Whip());
int cost = order.Cost();

IMO, both does same. If yes, what is the advantage of using decorator pattern here?

Any thoughts?

like image 717
Navaneeth K N Avatar asked Aug 08 '09 18:08

Navaneeth K N


2 Answers

No, they are not the same.

Head First example has 1 drink with Mocha, Whip, Roast added. Your example has 3 beverages.
See this Head First code. It works on the same instance of the beverage

beverage2 = new Mocha(beverage2);                                       
beverage2 = new DarkRoast(beverage2);                                       
beverage2 = new Whip(beverage2);

Your code creates 3 beverages (which means someone ordered 3 things separately).
In real life, it is not beverages, I guess. The beverage is one & flavors added on top of it.

The purpose of decorator is - to decorate. .Net has TextWriter and IndentedTextWriter (I guess), which basically takes the normal text of yours and applies indentation to it. It is similar to unix pipes in a way, if you think of it.

input -> tweaks -> tweaked input -> further tweaks -> further tweaked input.
Output of current operation becomes input for next operation.

I don't know if I explained it well.

like image 167
shahkalpesh Avatar answered Sep 26 '22 15:09

shahkalpesh


The whole point of the Decorator pattern is to add responsibilities via object composition, not inheritance. Inheritance is static, obj. composition is dynamic and more flexible. The possibilities for decoration are endless. It's also possible to un-decorate an object during runtime.

like image 44
Karl Avatar answered Sep 24 '22 15:09

Karl