Friday, November 28, 2014

Decorator Design Pattern

 

Type : Structural Design Pattern

 

Summary

Decorator Design pattern is used to extend or decorate certain objects statically or at run time.
Multiple Decorator can act on an object to add the desired behavior to a particular object instance without effecting other instances.
Decorator Design pattern is an Structural design pattern, it is alternative to inheritance/ Sub classing in java.
Java sub classing effects all the instances of the class, and some times it is not desirable to do so.


Advantage:

Unlike inheritance, you can choose any single object of a class  leaving the other instances unmodified.

Disadvantage:

Decorator Design Pattern increases the number of Classes in the Application.

Difference between Decorator and Visitor:

Decorator design pattern works on a single object.
Decorator design pattern helps in enhancing a single object with new functionality or behaviour.
Decorator is a Structural design pattern, Visitor is a behavioral design pattern.
Visitor works on composite objects.
Visitor pattern is used to add a new algorithm or functionality to collection of objects or hierarchy of objects.

Details:

Participants:

Component : Interface for object that might have Decorators applied
ConcreateComponent : Concrete objects that implements Component interface
Decorator: Maintains a reference to a Component Object
ConcreateDecorator: Implementations of Decorators that work on the referenced Component object to add behavior to them.

Sample Use Case

This Use Case is with example of Coffee. Let's Say We can have Different type of Coffee in a store with Different Types of Beans, Contents, Size and Price.  One option is to have Different Classes representing different Coffee , say JavaChipsCoffeeTall, JavaChipsWithSugarTall etc. 

In this example we are creating Different Decorators for Different Property of the Coffee to be served. Like for Size of the Coffee can have the following Decorators,

Size Decorators:

CoffeeTallSizeDecorator

CoffeeSmallSizeDecorator

Coffee Type Decorator:

CappuccinoCoffeeDecorator

JavaChipsCoffeeDecorator



Now we can apply a set of Decorators to get our desired cup of Coffee.

Class Diagram



Java Code Sample 

package dp.structural.decorator;

//Decorator Interface
public interface Coffee {

  void brewCofee();

  Double coffeePrice();
}



//Abstract Coffee Decorator
public abstract class CoffeeDecorator implements Coffee {

  private Coffee coffee;

  public CoffeeDecorator(Coffee coffee) {
    this.coffee = coffee;
  }

  public Coffee getCoffee() {
    return coffee;
  }

  public void setCoffee(Coffee coffee) {
    this.coffee = coffee;
  }

  @Override
  public void brewCofee() {
    System.out.println("Cappuccino::: adding raw coffee");
  }

  public Double coffeePrice() {
    return getCoffee().coffeePrice();
  }
}



//CoffeeTallSizeDecorator
public class CoffeeTallSizeDecorator extends CoffeeDecorator {

  public CoffeeTallSizeDecorator(Coffee coffee) {
    super(coffee);

  }


  @Override
  public void brewCofee() {
    getCoffee().brewCofee();
  }

  @Override
  public Double coffeePrice() {
    return getCoffee().coffeePrice() + 3;
  }
}


//JavaChipsCoffeeDecorator
public class JavaChipsCoffeeDecorator extends CoffeeDecorator {

  public JavaChipsCoffeeDecorator(Coffee coffee) {
    super(coffee);
  }

  @Override
  public void brewCofee() {
    // super.brewCofee();
    getCoffee().brewCofee();
    System.out.println("JavaChips:: Adding JavaChips Topping");
  }

  @Override
  public Double coffeePrice() {
    // TODO Auto-generated method stub
    return super.coffeePrice() + 2;
  }
}


//LatteCoffee Decorator
public class LatteCoffeeDecorator extends CoffeeDecorator {
  public LatteCoffeeDecorator(Coffee coffee) {
    super(coffee);
  }

  @Override
  public Double coffeePrice() {
    return getCoffee().coffeePrice() + 10;
  }
}


//Default Coffee
public class DefaultCoffee implements Coffee {

  @Override
  public void brewCofee() {
    System.out.println("### Preparing your coffee  Size :: Small");

  }

  @Override
  public Double coffeePrice() {
    return 1.5;
  }

}

//Demo of the Decorator Design Pattern
public class DecoratorPatternTest {

  public static void main(String[] args) {
    Coffee mycoFfee = new CoffeeTallSizeDecorator(
        new JavaChipsCoffeeDecorator(new CappuccinoCoffeeDecorator(new DefaultCoffee())));
    mycoFfee.brewCofee();
    System.out.println(mycoFfee.coffeePrice());
  }


}


No comments :

Post a Comment