Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / programming / architecture

Decorator Design Pattern in Java

4.75/5 (4 votes)
11 Feb 2013CPOL3 min read 57.1K   247  
It explains decorator design pattern in detail with example.

Introduction

The Decorator design pattern attaches additional responsibilities to an object dynamically. It is wrap up at another object. It will extend functionality of object without affecting any other object. Decorators provide an alternative to subclassing for extending functionality.

Also Known As

Wrapper

When to Use It

Use Decorator

  • to add responsibilities to individual objects dynamically without affecting other objects.
  • for responsibilities that can be withdrawn,
  • When extension by subclassing is impractical. Sometimes, a large number of independent extensions are possible and would produce an explosion of subclasses to support every combination. Or class definition may be hidden or otherwise unavailable for subclassing.

UML Diagram for Decorator Design Pattern

Image 1

Elements

  • Component
    • defines interface for objects that can have additional responsibilities added to them.
  • ConcreteComponent
    • defines an object on which additional responsibilities can be added
  • Decorator
    • maintains a reference to component object and defines an interface that conforms to component's interface. In simple words, it has a component object to be decorated.
  • ConcreteDecorator
    • add responsibilities to the component object.

Example

In this example, we will decorate a simple room with color and curtains.

Image 2
  • Room(Component)
    • It is an interface which creates a blue print for the class which will have decorators
  • SimpleRoom(ConcreteComponent)
    • Object of SimpleRoom class will be decorated. Additional responsibilities will be attached to it dynamically.
  • RoomDecorator(Decorator)
    • It contains reference to Room class which will be decorated.
  • ColorDecorator(ConcreteDecorator)

    • ColorDecorator will add additional responsibility i.e., add color to room.

  • CurtainDecorator(ConcreteDecorator)

    • CurtainDecorator will add additional responsibility i.e., add curtains to room.

Image 3

Logically, you can think of decorator pattern as shown in the above diagram. You will first create SimpleRoom object then decorate it with ColorDecorator object and then decorate resultant object with CuratainDecorator.

Java code for above classes:

The following interface is an interface depicting an room.

Room.java(Component):

Java
package org.arpit.javapostsforlearning.designPattern;

public interface Room{
  public String showRoom();
}

The following class is a concrete implementation of this interface. This is the base class on which the decorators will be added.

SimpleRoom.java(ConcreteComponent):

Java
package org.arpit.javapostsforlearning.designPattern;

public class SimpleRoom implements Room {

  @Override
  public String showRoom() {
    return "Normal Room";
  }

}

The 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.

RoomDecorator.java(Decorator):

Java
package org.arpit.javapostsforlearning.designpattern;

abstract class RoomDecorator implements Room{

  protected Room specialRoom;

  public RoomDecorator (Room specialRoom) {
    this.specialRoom= specialRoom;
  }

 public String showRoom() {
    return specialRoom.showRoom();
  }
}

The following class is our concrete decorator class. It extends abstract decorator. When this decorator is created, the base instance is passed to constructor which calls super class constructor. In showRoom() method, we call base class method followed by its own method addColors(). This addColors() adds functionality to base instance, i.e., decorating room with colors.

ColorDecorator.java(ConcreteDecorator):

Java
package org.arpit.javapostsforlearning.designpattern;

public class ColorDecorator extends RoomDecorator {

  public ColorDecorator (Room specialRoom) {
    super(specialRoom);
  }

  public String showRoom() {
    return specialRoom.showRoom() + addColors();
  }

  private String addColors() {
    return " + Blue Color";
  }
}

The following class is also concreteDecorator class similar to the above class. Here addCurtains() adds functionality to room(base instance), i.e., decorating room with curtains.

CurtainDecorator.java(ConcreteDecorator):

Java
package org.arpit.javapostsforlearning.designPattern;

public class CurtainDecorator extends RoomDecorator {

  public CurtainDecorator (Room specialRoom) {
    super(specialRoom);
  }

  public String showRoom() {
    return specialRoom.showRoom() + addCurtains();
  }

  private String addCurtains() {
    return " + Red Curtains";
  }
}

DecoratorDesignPatternMain.java:

Java
package org.arpit.javapostsforlearning.designpattern;  
public class DecoratorDesignPatternMain {  

 public static void main(String args[]) {  
  Room room = new CurtainDecorator(new ColorDecorator(new SimpleRoom()));  
  System.out.println(room.showRoom());  
 }  
}

I have created a simple Room and decorated that with color and curtains.

Output:

Normal room + Blue Color + Red Curtains

Advantages of Decorator Design Pattern

  • It is flexible than inheritance because inheritance adds responsibility at compile time but decorator pattern adds at run time.
  • We can have any number of decorators and also in any order.
  • It extends functionality of object without affecting any other object.

Disadvantage of Decorator Design Pattern

The main disadvantage of decorator design pattern is code maintainability because this pattern creates lots of similar decorators which are sometimes hard to maintain and distinguish.

Decorator Design Pattern in Java API

Java
java.io.BufferedReader;
java.io.BufferedWriter; 
java.io.FileReader;
java.io.Reader;

The above classes of Java API are designed using decorator design pattern.

References

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)