Decorator Pattern: attaches additional responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality.
Meet the decorator pattern:
For example, if the customer wants a Dark Roast with Mocha and Whip, then we'll:
1. Take a DarkRoast object
2. Decorate it with a Mocha object
3. Decorate it with a Whip object
4. Call the cost() method and rely on delegation to add on the condiment costs
Constructing a drink order with Decorators
1. We start with our DarkRoast Object
[IMG]http://i47.tinypic.com/iclhkl.jpg[/IMG]
2. The customer wants Mocha, so we create a Mocha object and wrap it around the DarkRoast.
[IMG]http://i46.tinypic.com/30uqm29.jpg[/IMG]
3. The customer also wants Whip, so we create a whip decorator and wrap Mocha with it
[IMG]http://i48.tinypic.com/2jabxva.jpg[/IMG]
4. Now its time to compute the cost for the customer. We do this by calling cost() on the outermost decorator, Whip, and Whip is going to delegate computing the cost to the objects it decorates. Once it gets a cost, it will add on the cost of the Whip.
[IMG]http://i50.tinypic.com/2zrg968.jpg[/IMG]
summary:
* Decorators have the same supertype as the objects they decorate.
* You can use one or more decorators to wrap an object
* Given that the decorator has the same supertype as the object it decorates, we can pass around a decorated object in place of the original (wrapped) object
* The decorator adds its own behavior either before and/or after delegating to the object it decorates to do the rest of the job. (KEY POINT)
* Objects can be decorated at any time, so we can decorate objects dynamically at runtime with as many decorators as we like.
Class diagram
[IMG]http://i48.tinypic.com/28h27hs.jpg[/IMG]
work our Starbuzz beverages into this framework
[IMG]http://i50.tinypic.com/2aifukh.jpg[/IMG]
beverages:
condiments:
Meet the decorator pattern:
For example, if the customer wants a Dark Roast with Mocha and Whip, then we'll:
1. Take a DarkRoast object
2. Decorate it with a Mocha object
3. Decorate it with a Whip object
4. Call the cost() method and rely on delegation to add on the condiment costs
Constructing a drink order with Decorators
1. We start with our DarkRoast Object
[IMG]http://i47.tinypic.com/iclhkl.jpg[/IMG]
2. The customer wants Mocha, so we create a Mocha object and wrap it around the DarkRoast.
[IMG]http://i46.tinypic.com/30uqm29.jpg[/IMG]
3. The customer also wants Whip, so we create a whip decorator and wrap Mocha with it
[IMG]http://i48.tinypic.com/2jabxva.jpg[/IMG]
4. Now its time to compute the cost for the customer. We do this by calling cost() on the outermost decorator, Whip, and Whip is going to delegate computing the cost to the objects it decorates. Once it gets a cost, it will add on the cost of the Whip.
[IMG]http://i50.tinypic.com/2zrg968.jpg[/IMG]
summary:
* Decorators have the same supertype as the objects they decorate.
* You can use one or more decorators to wrap an object
* Given that the decorator has the same supertype as the object it decorates, we can pass around a decorated object in place of the original (wrapped) object
* The decorator adds its own behavior either before and/or after delegating to the object it decorates to do the rest of the job. (KEY POINT)
* Objects can be decorated at any time, so we can decorate objects dynamically at runtime with as many decorators as we like.
Class diagram
[IMG]http://i48.tinypic.com/28h27hs.jpg[/IMG]
work our Starbuzz beverages into this framework
[IMG]http://i50.tinypic.com/2aifukh.jpg[/IMG]
public abstract class Beverage {
String description = “Unknown Beverage”;
public String getDescription() {
return description;
}
public abstract double cost();
}
public abstract class CondimentDecorator extends Beverage {
public abstract String getDescription();
}
beverages:
public class Espresso extends Beverage {
public Espresso() {
description = “Espresso”;
}
public double cost() {
return 1.99;
}
}
public class HouseBlend extends Beverage {
public HouseBlend() {
description = “House Blend Coffee”;
}
public double cost() {
return .89;
}
}
condiments:
public class Mocha extends CondimentDecorator {
Beverage beverage;
public Mocha(Beverage beverage) {
this.beverage = beverage;
}
public String getDescription() {
return beverage.getDescription() + “, Mocha”;
}
public double cost() {
return .20 + beverage.cost();
}
}