The Pragmatic Craftsman :: Simplicity from complexity ::

The Decorator Pattern

I’ve been inthe dark as far as the Decorator pattern is concerned. I knew, inprinciple, how it works, but I can see that my understanding was veryincomplete. Plus, I never had a chance to useit. While reading the Head First Design Patternsbook, Idiscovered something basic that: when you wrap an object several timesand then call a method on it, it will be called as many times as it waswrapped. The trick? Keepa reference to the object — you’re creating a chain.

Let me gothrough this step by step. By example. This is thebook’s example, the Starbuzz Coffee decorator.

A simpleinterface.

 

public interfaceBeverage {

public String getDescription();

public BigDecimal getCost();

}

We have severalcoffee types, Dark Roast being one of them.

public classDarkRoast implementsBeverage {

  public BigDecimal getCost() {

     return newBigDecimal(“1.55″);

  public String getDescription() {

    return“Dark Roast”;

  }

}

When orderingcoffee, you can pick a coffee type (Dark Roast, Latte, etc), and youcan also add on to the coffee. For instance, you can add a whip creamon top, or add a shot of expresso to it. Which, of course, adds to theprice. You could extend Beverage with all of the types, but that’s toomany classes. Here’swhere the decorator pattern comes into play.

Here’sthe solution. You define the AddOnDecorator and extend it with thedifferent add ons.

/** It’sjust an empty class */

public abstractclassAddOnDecorator implementsBeverage { }

public classExpresso extendsAddOnDecorator {

Beveragebeverage;

public Expresso(Beverage beverage) {

  this.beverage =beverage;

}

public BigDecimal getCost() {

  return newBigDecimal(“0.25″).add(beverage.getCost());

}

public String getDescription() {

  return beverage.getDescription()+ “, with Expresso”;

}

public classWhip extendsAddOnDecorator {

Beveragebeverage;

public Whip(Beverage beverage) {

this.beverage =beverage;

 

public BigDecimal getCost() {

return newBigDecimal(“0.10″).add(beverage.getCost());

 

public String getDescription() {

return beverage.getDescription()+ “, Whipped”;

}

}

public classStarbuzzCoffee {

public staticvoidmain(String[] args) {

BeveragedarkRoast = newDarkRoast();

darkRoast= newExpresso(darkRoast);

darkRoast= newWhip(darkRoast);

System.out.println(darkRoast.getDescription()+ ” costs “

+darkRoast.getCost());

}

}

WhenI first looked at the code, I was confused. I thought that newWhip(…) would just override it,right?

Thisis what gets printed: Dark Roast, with Expresso, Whippedcosts 1.90

You get the beverage you want(DarkRoast), you pass it to the Expresso wrapper, which in turn passesit to the Whip wrapper.

Firstthe Expressowrapper is called, itreceives the dark roast beverage. Then the dark roast is passed againto the Whip wrapper. If you look closely (and this isa little confusing), when an Expresso is instantiated, it receives the beverage andmakes a local copy (so it is never lost). Essentially, a chain is made.When the action on the final object is made, the chain is traversed andthe beverage object is passed around. That’s how this patternworks. (Wow, I learn something (basic) every day. :-) )

The Decoratorpattern is cool. It rocks. :-) It lets you keep adding functionality and still keep the objectscohesive (as you’re not bloating the objects). No coupling as well.Nice.

Reference
Head First Design Patterns, the example above was taken from the book

Comments are closed.

Random Quote

Topics

Tags

Archive

Recent Entries

Currently Reading

Shelfari: Book reviews on your book blog

:: The Pragmatic Craftsman recommends

:: The Pragmatic Craftsman book reviews

Info

© 2001-2010 Stanley Kubasek About me :: Contact me

@PragCraftsman on Twitter

I put Code Complete #1 over Martin's book because it has "awaken" me as a programmer. But other than that, Martin's book is the best! - 6 hours ago@mcory1 First of all, @unclebobmartin is my hero! Agile Software Development, Principles, Patterns, and Practices is my #2. SOLID rules! :) - 6 hours agoWhich programming book has had the most influence on your career? I have to say "Code Complete" by McConnell - 19 hours agoI have not used Git myself, but see a lot of good buzz about it. Is this anology accurate: Git is to SVN as SVN is to CVS? #git #svn - 1 day ago