Decorator
design pattern is used to enhance the functionality/responsibility of a
particular object at run-time or dynamically.
The
decorator pattern applies when there is a need to dynamically add as well as
remove responsibilities to a class, and when sub-classing would be impossible
due to the large number of sub-classes that could result.
Decorator
design pattern is based on abstract classes and we derive concrete
implementation from those classes.
At
the same time other instance of same class will not be affected by this so
individual object gets the new behavior.
Implementation of
Decorator pattern:
Coffee making
scenario
Coffee.java
/**
* The interface Coffee defines the functionality of Coffee implemented by decorator
* @author rajesh.dixit
*/
public interface Coffee {
/** @return Returns the cost of the coffee.*/
public double getCost();
/** @return Returns the ingredients of the coffee */
public String
getIngredients();
}
SimpleCoffee.java
/**
* Extension of a simple coffee without any extra ingredients
* @author rajesh.dixit
*/
public class SimpleCoffee implements Coffee {
@Override
public double getCost() {
return 1;
}
@Override
public String
getIngredients() {
return "Coffee";
}
}
CoffeeDecorator.java
/**
* Abstract decorator class - note that it implements
Coffee interface
* @author rajesh.dixit
*/
public abstract class CoffeeDecorator implements Coffee {
protected final Coffee decoratedCoffee;
public CoffeeDecorator(Coffee c) {
this.decoratedCoffee = c;
}
/** Implementing methods of the interface.
*/
public double getCost() {
return decoratedCoffee.getCost();
}
public String getIngredients() {
return decoratedCoffee.getIngredients();
}
}
/**
* Decorator WithMilk mixes milk into coffee.
* Note it extends CoffeeDecorator.
* @author rajesh.dixit
*/
class WithMilk extends CoffeeDecorator {
public WithMilk(Coffee c) {
super(c);
}
/** Overriding methods defined in the abstract superclass
*/
public double getCost() {
return super.getCost() + 0.5;
}
public String getIngredients() {
return super.getIngredients() + ", Milk";
}
}
/**
* Decorator WithSprinkles mixes sprinkles onto coffee.
* Note it extends CoffeeDecorator.
* @author rajesh.dixit
*/
class WithSprinkles extends CoffeeDecorator {
public WithSprinkles(Coffee c) {
super(c);
}
public double getCost() {
return super.getCost() + 0.2;
}
public String getIngredients() {
return super.getIngredients() + ", Sprinkles";
}
}
TestDecorator.java
public class TestDecorator {
public static void main(String[] args) {
Coffee
c = new SimpleCoffee();
print(c);
c
= new WithMilk(c);
print(c);
c
= new
WithSprinkles(c);
print(c);
}
public static void print(Coffee c) {
System.out.println("Cost: " + c.getCost() + "; Ingredients: "
+
c.getIngredients());
}
}
Output:
Cost: 1.0; Ingredients: Coffee
Cost: 1.5; Ingredients: Coffee, Milk
Cost: 1.7; Ingredients: Coffee, Milk,
Sprinkles
Usage in JDK:
1. All
subclasses of java.io.InputStream, OutputStream, Reader and Writer have a
constructor taking an instance of same type.
2. java.util.Collections,
the checkedXXX(), synchronizedXXX() and unmodifiableXXX() methods.
3. javax.servlet.http.HttpServletRequestWrapper
and HttpServletResponseWrapper.
4. Graphical User Interface Frameworks
GUI
toolkits use decoration pattern to add functionalities dynamically as explained
before.
5. In Mobiquity, to load all ValidationService and MComService and decorate them as business rules(TCP, PIN Check and All).
Reference:
No comments:
Post a Comment