Decorator pattern

Decorator pattern Overview

Its classified as structural design pattern as its used to form a large object structure for a specific object.

This pattern is mainly used to modify the behaviour of specific object at runtime.

It means we can modify the behaviour of specific object without altering the behaviour of other objects of the same class.

If we use inheritance or composition to extend the behaviour of object then its applicable to all the instances of the class and this happens at compile time itself, we can’t add behaviour at run time.

Decorator pattern is the perfect solution to add behaviour at runtime for a specific object without altering other objects of a class.

How it’s possible to modify the behaviour of one object of a class without altering other objects of same class?

Decorator pattern uses abstract class or interface with composition to inject new behaviour at runtime


Let’s understand few terms before implementing this pattern


decore_design-pattern_1

Component
It’s an interface or abstract class defined for objects that can have additional responsibilities added to them.

ConcreteComponent
It’s a java class which defines an object on which additional responsibilities will be added

Decorator
It defines an interface that conforms to component’s interface. In other words, it extends Component

ConcreteDecorator
It’s a java class which adds responsibilities to the component object.In other words, It just decorates the concrete component

Requirement:

Provide additional functionality called “Color” to few electronics Products in our system at runtime.

Let’s implement this pattern for above requirement


Product(Component)
o It is an interface which creates a blue print for the class which uses decorators

ElectronicProduct(ConcreteComponent)
o Object of ElectronicProduct class will be decorated by providing additional responsibilities to it dynamically.

ProductDecorator(Decorator)
o It acts as a base decorator

ProductColorDecorator(ConcreteDecorator)
o ProductColorDecorator will add additional responsibility i.e., adds color to Product.

Let’s convert above diagram into code to implement this pattern


Decore_design_pattern_Example

Step 1

Create an Interface called Product and add a method called displayProduct()

  1. public interface Product{
  2.   public String displayProduct();
  3. }
public interface Product{
  public String displayProduct();
}

Step 2

Create a concrete class called “ElectronicsProduct” by implementing above interface

  1. public class ElectronicsProduct implements Product {
  2.  
  3.   @Override
  4.   public String displayProduct() {
  5.     return "Electronic Product";
  6.   }
  7.  
  8. }
public class ElectronicsProduct implements Product {

  @Override
  public String displayProduct() {
    return "Electronic Product";
  }

}

Step 3

Create an abstract decorator called “ProductDecorator”

  1. abstract class ProductDecorator implements Product{
  2.  
  3.  public abstract String displayProduct();
  4. }
abstract class ProductDecorator implements Product{

 public abstract String displayProduct();
}

Step 4

Create a concrete decorator class called “ProductColorDecorator” by implementing above abstract decorator

  1. public class ProductColorDecorator extends ProductDecorator {
  2.  
  3.  protected Product product;
  4.   public ProductColorDecorator (Product product) {
  5.     this.product=product;
  6.   }
  7.  
  8.   @Override
  9.   public String displayProduct() {
  10.     return product.displayProduct() +" -> Red Color";
  11.   }
  12. }
public class ProductColorDecorator extends ProductDecorator {

 protected Product product;
  public ProductColorDecorator (Product product) {
    this.product=product;
  }

  @Override
  public String displayProduct() {
    return product.displayProduct() +" -> Red Color";
  }
}

Step 5

Test the pattern

  1. public class DecoratorDesignPatternTest {  
  2.  
  3.  public static void main(String args[]) {  
  4. Product product1 =new ElectronicsProduct(); // No decorator
  5. System.out.println(product1.displayProduct());  
  6.   Product product2 = new ProductColorDecorator(new ElectronicsProduct()));  //Decorator for object of same class
  7.   System.out.println(product2.displayProduct());  
  8.  }  
  9. }
public class DecoratorDesignPatternTest {  

 public static void main(String args[]) {  
Product product1 =new ElectronicsProduct(); // No decorator
System.out.println(product1.displayProduct());  
  Product product2 = new ProductColorDecorator(new ElectronicsProduct()));  //Decorator for object of same class
  System.out.println(product2.displayProduct());  
 }  
}



When to use this pattern?


When we have a requirement of modifying the object behaviour at runtime

Whenever we want to provide additional responsibilities or behaviour to few objects of a class rather than for all the objects of the same class.

In other words, we can add functionality to a single object and leave others unmodified

When we need to avoid too much of sub-classing to add additional responsibilities

When we need to achieve open closed principle(Open for extension and Closed for modification)

Note:
Java I/O Streams implementation has already implemented this pattern.

About the Author

Founder of javainsimpleway.com
I love Java and open source technologies and very much passionate about software development.
I like to share my knowledge with others especially on technology 🙂
I have given all the examples as simple as possible to understand for the beginners.
All the code posted on my blog is developed,compiled and tested in my development environment.
If you find any mistakes or bugs, Please drop an email to kb.knowledge.sharing@gmail.com

Connect with me on Facebook for more updates

Share this article on