1. Make a base class for an object you want to "decorate".
2. Make an abstract extension of that class and name it a decorator class name.
3. Make decorators by making non abstract classes that extend the decorator class and add "decorations" (functionality) to these classes. Make sure that the constructor of each of the new classes receives an object that is of type decorator.
4. Create an object of type one decorator extended class, pass an object that is a type two decorator class to the type one's constructor and so on as long as you have "decorations" you want to add and than in the deepest inclusion make an object of the original base class passed as an argument.
5. Execute the method that will call all passed decorators' equivalent methods to add their decorations and in that way you will have the base class object build with all desired "decorations" around it.
To be honest, it is a very strange design concept in OO programming.
Why are you interested in it? Purely educational or you want to make something concrete of it? If that is the case, maybe you should consider a more elegant approach, depending on the problem you are trying to solve.
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.
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();
}
The above is an interface depicting an icecream. I have kept things as simple as possible so that the focus will be on understanding the design pattern. Following class is a concrete implementation of this interface. This is the base class on which the decorators will be added.
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 {
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.