To extend or modify the behaviour of ‘an instance’ at runtime decoratordesign patternis used. Inheritance is used to extend the abilities of ‘a class’. Unlike inheritance, you can choose any single object of a class andmodify its behaviourleaving the other instances unmodified.
In implementing the decorator pattern you construct a wrapper around an object by extending its behavior. The wrapper will do its job before or after and delegate the call to the wrapped instance.
Design of decorator pattern
You start with an interface which creates a blue print for the class which will have decorators. Then implement that interface with basic functionalities. Till now we have got an interface and an implementation concrete class. Create an abstract class that contains ( aggregation relationship ) an attribute type of the interface. The constructor of this class assigns the interface type instance to that attribute. This class is the decorator base class. Now you can extend this class and create as many concrete decorator classes. The concrete decorator class will add its own methods. After / before executing its own method the concrete decorator will call the base instance’s method. Key to this decorator design pattern is the binding of method and the base instance happens at runtime based on the object passed as parameter to the constructor. Thus dynamically customizing the behavior of that specific instance alone.
Decorator Design Pattern – UML Diagram
Implementation of decorator pattern
Following given example is an implementation of decorator design pattern. Icecream is a classic example for decorator design pattern. You create a basic icecream and then add toppings to it as you prefer. The added toppings change the taste of the basic icecream. You can add as many topping as you want. This sample scenario is implemented below.
package
com.javapapers.sample.designpattern;
public
interface
Icecream {
public
String makeIcecream();
}
package
com.javapapers.sample.designpattern;
public
class
SimpleIcecream
implements
Icecream {
@Override
public
String makeIcecream() {
return
"Base Icecream"
;
}
}
|
Following class is the decorator class. It is the core of the decorator design pattern. It contains an attribute for the type of interface. Instance is assigned dynamically at the creation of decorator using its constructor. Once assigned that instance method will be invoked.
package
com.javapapers.sample.designpattern;
abstract
class
IcecreamDecorator
implements
Icecream {
protected
Icecream specialIcecream;
public
IcecreamDecorator(Icecream specialIcecream) {
this
.specialIcecream = specialIcecream;
}
public
String makeIcecream() {
return
specialIcecream.makeIcecream();
}
}
|
Following two classes are similar. These are two decorators, concrete class implementing the abstract decorator. When the decorator is created the base instance is passed using the constructor and is assigned to the super class. In the makeIcecream method we call the base method followed by its own method addNuts(). This addNuts() extends the behavior by adding its own steps.
package
com.javapapers.sample.designpattern;
public
class
NuttyDecorator
extends
IcecreamDecorator {
public
NuttyDecorator(Icecream specialIcecream) {
super
(specialIcecream);
}
public
String makeIcecream() {
return
specialIcecream.makeIcecream() + addNuts();
}
private
String addNuts() {
return
" + cruncy nuts"
;
}
}
|
package
com.javapapers.sample.designpattern;
public
class
HoneyDecorator
extends
IcecreamDecorator {
public
HoneyDecorator(Icecream specialIcecream) {
super
(specialIcecream);
}
public
String makeIcecream() {
return
specialIcecream.makeIcecream() + addHoney();
}
private
String addHoney() {
return
" + sweet honey"
;
}
}
|
Execution of the decorator pattern
I have created a simple icecream and decorated that with nuts and on top of it with honey. We can use as many decorators in any order we want. This excellent flexibility and changing the behaviour of an instance of our choice at runtime is the main advantage of the decorator design pattern.
package
com.javapapers.sample.designpattern;
public
class
TestDecorator {
public
static
void
main(String args[]) {
Icecream icecream =
new
HoneyDecorator(
new
NuttyDecorator(
new
SimpleIcecream()));
System.out.println(icecream.makeIcecream());
}
}
|
Output
Base Icecream + cruncy nuts + sweet honey
|
Decorator Design Pattern in java API
java.io.BufferedReader;
java.io.FileReader;
java.io.Reader;
The above readers of java API are designed using decorator design pattern.
本文转载自: http://javapapers.com/design-patterns/decorator-pattern/版权所有