You are here:   ArielOrtiz.com > Software Design and Architecture > Decorator Pattern

Decorator Pattern

This example was taken from [FREEMAN] pp. 79-98. Write the code that allows us to model coffee beverages using the Decorator pattern. The following tables show what beverages and condiments are available, and their corresponding prices:

Beverages
Name Price
Dark Roast Coffee $0.99
Espresso $1.99
House Blend Coffee $0.89
Condiments
Name Price
Mocha $0.20
Whip $0.10
Soy $0.15
Milk $0.10

In our design, the condiments will decorate the beverages. The following Ruby code demonstrates how your code could be used:

beverage = DarkRoast.new
beverage = Mocha.new(beverage)
beverage = Whip.new(beverage)
puts beverage.description
puts beverage.cost

For this example, the expected output should be:

Dark Roast Coffee, Mocha, Whip
1.29

The following image depicts the way the decorators work when the cost method is called from the above code.

A decorated beverage.

The following UML diagram shows the class hierarchy. Each class needs to implement one or several of these methods: initialize, description, and cost.

Beverage class hierarchy.

All these classes should be placed in the coffee.rb source file.

The following unit tests verify the correct behavior of your classes. Place the test class in the test_coffee.rb source file.

require 'test/unit'
require 'coffee'

class MyTest < Test::Unit::TestCase

  def test_espresso
    beverage = Espresso.new    
    assert_equal("Espresso", beverage.description)
    assert_equal(1.99, beverage.cost)
  end
  
  def test_dark_roast
    beverage = DarkRoast.new
    beverage = Milk.new(beverage)    
    beverage = Mocha.new(beverage)
    beverage = Mocha.new(beverage)
    beverage = Whip.new(beverage)        
    assert_equal("Dark Roast Coffee, Milk, Mocha, Mocha, Whip", beverage.description)
    assert_equal(1.59, beverage.cost)
  end
  
  def test_house_blend
    beverage = HouseBlend.new
    beverage = Soy.new(beverage)
    beverage = Mocha.new(beverage)
    beverage = Whip.new(beverage)
    assert_equal("House Blend Coffee, Soy, Mocha, Whip", beverage.description)
    assert_equal(1.34, beverage.cost)
  end
  
end
© 1996-2010 by Ariel Ortiz (ariel.ortiz@itesm.mx)
Made with Django | Licensed under Creative Commons | Valid XHTML | Valid CSS