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:
| Name | Price |
|---|---|
| Dark Roast Coffee | $0.99 |
| Espresso | $1.99 |
| House Blend Coffee | $0.89 |
| 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.
The following UML diagram shows the class hierarchy. Each class
needs to implement one or several of these methods:
initialize, description, and
cost.
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