Friday, February 28, 2014

Structural Design Patterns: Decorator Design Pattern



Decorator pattern allows to add new functionality an existing object without altering its structure. This type of design pattern comes under structural pattern as this pattern acts as a wrapper to existing class.

This pattern creates a decorator class which wraps the original class and provides additional functionality keeping class methods signature intact.

As per GOF Design pattern , definition of Decorator Design pattern is “Attach additional responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality.”




The decorator pattern attaches additional responsibilities to an object dynamically. Decorators provide a flexible alternative to sub classing for extending functionality.
When to use ?
  • A data whenever changed should be distributed to all the relevant subscribers immediately.
  • Whenever a subscriber unsubscribes for the data the code pertaining to the publisher should not change.
  • Whenever new subscriber subscribes for the data the code pertaining to the publisher should not change.
 


The decorator pattern is a structural design pattern. Whereas inheritance adds functionality to classes, the decorator pattern adds functionality to objects by wrapping objects in other objects. Each time additional functionality is required, the object is wrapped in another object. Java I/O streams are a well-known example of the decorator pattern.

 To extend or modify the behavior of ‘an instance’ at runtime decorator design pattern is used. Inheritance is used to extend the abilities of ‘a class’. Unlike inheritance, you can choose any single object of a class and modify its behaviour leaving the other instances unmodified.

The Decorator design pattern takes a different approach. Instead of  using external algorithms, this design pattern is all about using wrapper code to extend your core code.


Decorator design pattern is used to modify the functionality of an object at runtime. At the same time other instances of the same class will not be affected by this, so individual object gets the modified behavior. Decorator design pattern is one of the structural design pattern and uses abstract classes or interface with composition to implement.
We use inheritance or composition to extend the behavior of an object but this is done at compile time and it’s applicable to all the instances of the class. We can’t add any new functionality of remove any existing behavior at runtime – this is when Decorator pattern comes into picture.
 

Example 1 :  While purchasing computer we have multiple things bounded to values



We can start coding by creating the core component, which is the computer the example the computer itself. Now how about creating some decorator classes? Such classes have to act as wrappers for the Computer class, which means that variables that can hold computer
objects should also be able to hold objects that wrap computer objects. And one easy way to make sure that can happen is to extend the wrapper classes from the Computer class.


1:  public class Computer {  
2:    public Computer() { }  
3:    public String description(){  
4:         return "computer";  
5:    }  
6:  }  



Alright, that’s the core component: the computer itself. Such classes have to act as wrappers for the Computer class, which means that variables that can hold computer objects should also be able to hold objects that wrap computer objects. And one easy way to make sure that can happen is to extend the wrapper classes from the Computer class.


Creating a decorator 

You might start by creating an abstract class that all Computer class wrappers have to extend


1:  public abstract class ComponentDecorator extends Computer {  
2:       public abstract String description();  
3:  } 

 
1:  public class Disk extends ComponentDecorator {  
2:       Computer c ;  
3:       public Disk(Computer a) {  
4:        c = a;  
5:       }  
6:       @Override  
7:       public String description() {  
8:            return c.description() + " and a Disk";  
9:       }  
10:  }  

1:  public class Monitor extends ComponentDecorator {  
2:       Computer computer;  
3:       public Monitor(Computer c){  
4:            computer = c;  
5:       }  
6:       @Override  
7:       public String description() {  
8:            return computer.description() + " and Monitor";  
9:       }  
10:  }  

1:  public class CD extends ComponentDecorator {  
2:       Computer computer;  
3:       public CD(Computer c){  
4:            computer = c;  
5:       }  
6:       @Override  
7:       public String description() {  
8:            return computer.description() + " and with CD ";  
9:       }  
10:  }  

1:  public class DecoTest {  
2:       public static void main(String[] args) {  
3:            Computer computer = new Computer();  
4:            computer = new Disk(computer);  
5:            computer = new Monitor(computer);  
6:            computer = new CD(computer);  
7:            computer = new CD(computer);  
8:            System.out.println("You’re getting a " + computer.description()     + ".");  
9:       }  
10:  }  



Output will be like below

You’re getting a computer and a Disk and Monitor and with CD and with CD.




Example 2 : 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.




The above is an interface depicting an icecream


1:  public interface IceCream {  
2:       public String makeIcecream();  
3:  }  


1:  public class SimpleIcecream implements IceCream {  
2:       @Override  
3:       public String makeIcecream() {  
4:            return "Base Ice Cream";  
5:       }  
6:  }  



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

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.



1:  public abstract class IcecreamDecorator implements IceCream {  
2:       protected IceCream iceCream ;  
3:       public IcecreamDecorator(IceCream i) {  
4:            iceCream = i;  
5:       }  
6:       @Override  
7:       public String makeIcecream() {  
8:            return iceCream.makeIcecream();  
9:       }  
10:  }  



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() and getHoeny()



1:  public class NuttyDecorator extends IcecreamDecorator {  
2:       public NuttyDecorator(IceCream i) {  
3:            super(i);  
4:       }  
5:       public String makeIcecream() {  
6:            return iceCream.makeIcecream() + addNuts();  
7:       }  
8:       private String addNuts() {  
9:            return " + Nuts ";  
10:       }  
11:  }  

 
1:  public class HoneyDecorator extends IcecreamDecorator {  
2:       public HoneyDecorator(IceCream i) {  
3:            super(i);  
4:       }  
5:       @Override  
6:       public String makeIcecream() {  
7:            return iceCream.makeIcecream() + getHoney();  
8:       }  
9:       private String getHoney() {  
10:            return " + Real Honey";  
11:       }  
12:  }  

 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.



1:  public class TestDecorator {  
2:       public static void main(String[] args) {  
3:            IceCream icecream = new HoneyDecorator(new NuttyDecorator(new SimpleIcecream()));  
4:         System.out.println(icecream.makeIcecream());  
5:       }  
6:  }  





Output will be like below

Base Ice Cream + Nuts  + Real Honey





Decorator Design Pattern in java API

java.io.BufferedReader;
java.io.FileReader;
java.io.Reader

A typical usage of Decorator pattern is Java IO classes.
Here is a simple example – BufferedReader decorates InputStreamReader.
BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
//System.in is an InputStream object
InputStreamReader(InputStream in) bridge from byte streams to character streams. InputSteamReader reads bytes and translates them into characters using the specified character encoding.
BufferedReader(Reader in) – read text from a character stream and buffer characters in order to provide efficient reading methods(e.g., readLine())

 Consequences
  • Decoration is more convenient for adding functionalities to objects instead of entire classes at runtime. With decoration it is also possible to remove the added functionalities dynamically.
  • Decoration adds functionality to objects at runtime which would make debugging system functionality harder.

Related Patterns
  • Adapter Pattern - A decorator is different from an adapter in that a decorator changes object's responsibilities, while an adapter changes an object interface.
  • Composite Pattern - A decorator can be viewed as a degenerate composite with only one component. However, a decorator adds additional responsibilities.

Notes :
Advantage :  No explosion of classes. Maintenance is easy.
Can you explain the decorator design pattern?
A. By 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. The decoration happens at run-time. In Java, the wrapper classes like Integer, Double, etc are typical example of a decorator pattern. Another good example is the Java I/O classes as shown below. Each reader or writer will decorate the other to extend or modify the behavior.
?
1
2
3
4
5
String inputText = "Some text to read";
ByteArrayInputStream bais = new ByteArrayInputStream(inputText.getBytes());
Reader isr = new InputStreamReader(bais);
BufferedReader br = new BufferedReader(isr);
br.readLine();

As you can see, each reader extends the behavior at run-time. This is the power of object composition as opposed to inheritance. By composing a fewer classes at run-time, desired behavior can be created. Here is another example demonstrating an interleaved reading using a class from the Apache library.

Q. How does a decorator design pattern differ from a proxy design pattern?
A. In Proxy pattern, you have a proxy and a real subject. The relationship between a proxy and the real subject is typically set at compile time, whereas decorators can be recursively constructed at run time. The Decorator Pattern is also known as the Wrapper pattern. The Proxy Pattern is also known as the Surrogate pattern. The purpose of decorator pattern is to add additional responsibilities to an object. These responsibilities can of course be added through inheritance, but composition provides better flexibility as explained above via the Java I/O classes. The purpose of the proxy pattern is to add an intermediate between the client and the target object. This intermediate shares the same interface as the target object. Here are some scenarios in which a proxy pattern can be applied.
  • A remote proxy provides a local representative for an object in a different address space.Providing interface for remote resources such as web service or REST resources or EJB using RMI.
  • A virtual proxy creates expensive object on demand.
  • A protection proxy controls access to the original object.Protection proxies are useful when objects should have different access rights.
  • A smart reference is a replacement for a bare pointer that performs additional actions when an object is accessed.
  • Adding a thread-safe feature to an existing class without changing the existing class's code. This is useful when you do not have the freedom to fix thread-safety issues in a third-party library.



Difference between Decorator and Proxy pattern in Java? 

Another tricky Java design pattern question and trick here is that both Decorator and Proxy implements interface of the object they decorate or encapsulate. As I said, many Java design pattern can have similar or exactly same structure but they differ in there intent. Decorator pattern is used to implement functionality on already created object, while Proxy pattern is used for controlling access to object. One more difference between Decorator and Proxy design pattern is that, Decorator doesn't create object, instead it get object in it's constructor, while Proxy actually creates objects.
 































































No comments: