struts2spring

November 12, 2009

Decorator Pattern

Filed under: Design Patterns, Java EE — struts2spring @ 3:55 PM

The Decorator Pattern attaches additional responsibilities to an object dynamically. Decorators provide a flexible alternative to sub-classing for extending functionality.
— Head-first Design Pattern

I have learned there are ways of “inheriting” behavior at run-time through composition and delegation. When I inherit behavior by sub-classing, that behavior is set statically at compile time. In addition, all subclasses must inherit the same behavior. If however, I can extend an object’s behavior through composition, then I can do this dynamically at run-time.

headfirst.decorator.starbuzz

The Decorator Pattern allows for the dynamic wrapping of objects in order to modify their existing responsibilities and behaviors.
Now The question comes when to use decorator pattern.

Here are some points when to use decorator pattern.

Use When:

  • Object responsibilities and behaviors should be dynamically modifiable.
  • Concrete implementations should be decoupled from responsibilities and behaviors.
  • Subclassing to achieve modification is impractical or impossible.
  • Specific functionality should not reside high in the object hierarchy.
  • A lot of little objects surrounding a concrete implementation is acceptable.

StarbuzzCoffee.java

package headfirst.decorator.starbuzz;
public class StarbuzzCoffee {
 public static void main(String args[]) {
 Beverage beverage = new Espresso();
 System.out.println(beverage.getDescription() + " $" + beverage.cost());

 Beverage beverage2 = new DarkRoast();
 beverage2 = new Mocha(beverage2);
 beverage2 = new Mocha(beverage2);
 beverage2 = new Whip(beverage2);
 System.out.println(beverage2.getDescription() + " $" + beverage2.cost());

 Beverage beverage3 = new HouseBlend();
 beverage3 = new Soy(beverage3);
 beverage3 = new Mocha(beverage3);
 beverage3 = new Whip(beverage3);
 System.out.println(beverage3.getDescription() + " $" + beverage3.cost());
 }
}
Beverage.java
package headfirst.decorator.starbuzz;
public abstract class Beverage {
 String description = "Unknown Beverage";
 public String getDescription() {
 return description;
 }

 public abstract double cost();
}

CondimentDecorator.java

package headfirst.decorator.starbuzz;
public abstract class CondimentDecorator extends Beverage {
 public abstract String getDescription();
}
DarkRoast.java
package headfirst.decorator.starbuzz;

public class DarkRoast extends Beverage {
 public DarkRoast() {
 description = "Dark Roast Coffee";
 }

 public double cost() {
 return .99;
 }
}

Decaf.java
package headfirst.decorator.starbuzz;

public class Decaf extends Beverage {
 public Decaf() {
 description = "Decaf Coffee";
 }

 public double cost() {
 return 1.05;
 }
}

Mocha.java
package headfirst.decorator.starbuzz;

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();
 }
}


Real World Decorators: Java I/O

decorationthe java io

Draw back of decorator pattern is, overuse can be complex.

Blog at WordPress.com.