Decorator Pattern

Decorator Pattern is a structural pattern.

Motive: Attach additional responsibilities to an object dynamically. Decorators provide a flexible alternative to sub classing for extending functionality. This is also called “Wrapper”.

Where To Use :

  1. To add responsibilities to individual objects dynamically without affecting other objects.
  2. When extension by sub classing is impractical. Sometimes a large number of independent extensions are possible and would produce an explosion of subclasses to support every combination. Or a class definition may be hidden or otherwise unavailable for sub classing.

Real Life Example:

  • Java Swing components E.g. JComponent (extends Container)
  • Java I/O classes

Buffered Stream – adds buffering for the stream
Data Stream – allows I/O of primitive Java data types
Pushback Stream – allows undo operation

Example: Explosion of subclasses

Suppose we have a TextView GUI component and we want to add different kinds of borders and scrollbars to it. Suppose we have three types of borders: Plain, 3D, Fancy and two types of scrollbars: Horizontal, Vertical

Decorator Problem

Decorator Problem

Case Study:

Write a decorator that converts all uppercase characters to lowercase in the input stream.

Requirement:
Convert all alphabet to lower case while reading file.  E.g. If Input read “I know the Decorator Pattern therefore I RULE!” then decorator converts this to “i know the decorator pattern therefore i rule!”

Explanation:

  • Abstract Component – InputStream
  • Concrete Components – FileInputStream, StringBufferInputStream, ByteArrayInputStream
  • Abstract Decorator – FilterInputStream
  • Concrete Decorator – InputStreamDecorator

Note:

  1. Abstract Decorator extends Abstract Component.
  2. Abstract Decorator (FilterInputStream)  Decorators implement the same interface or abstract class as the component they are going to decorate.
  3. The Concrete Component (FileInputStream) is the object we’re going to dynamically add new behavior to. It extends Component.

Class Diagram:

Decorator Pattern

Decorator Pattern

  • Decorators have the same super type as the objects they decorate.
  • You can use one or more decorators to wrap an object.
  • Given that the decorator has the same super type as the object it decorates, we can pass around a decorated object in place of the original (wrapped) object.
  • The decorator adds its own behavior either before and/or after delegating to the object it decorates to do the rest of the job.
  • Objects can be decorated at any time, so we can decorate objects dynamically at runtime with as many decorators as we like.

Code:

Abstract Component – InputStream – Refer Java API Source

Concrete Components – FileInputStream Refer Java API Source

Abstract Decorator – FilterInputStream Refer Java API Source

Concrete Decorator Class: InputStreamDecorator

package com.structural.decorator;

import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;

/**
 * This sample is taken from Head First. InputStreamDecorator decorate IO class
 * to convert all upper case characters to lower case in the input stream. <br>
 * 1) Extend the abstract decorator for all Input Stream. Note that
 * FilterInputStream extends InputStream

 * 2) Composition – InputStream via contructor.

 * 3) Implement two read method within InputStream.

 *
 * Note: <br>
 * The Decorator Pattern attach additional responsibilities to an object
 * dynamically. <br>
 * A) Decorators provide a flexible alternative to subclassing for
 * extending functionality. Inheritance is one form of extension, but not
 * necessarily the best way to achieve flexibility in our designs. Composition
 * and delegation can often be used to add new behaviors at runtime <br>
 * B) Decorators have the same supertype as the objects they decorate

 * C) The decorator adds its own behavior either before and/or after delegating to the
 * object it decorates to do the rest of the job.
 *
 * @author Shishir Kumar
 */
public class InputStreamDecorator extends FilterInputStream {

 protected InputStreamDecorator(InputStream in) {
  super(in);
 }

 public int read() throws IOException {
  int c = super.read();
  return (c == -1 ? c : Character.toLowerCase((char) c));
 }

 public int read(byte[] b, int offset, int len) throws IOException {
  int result = super.read(b, offset, len);
  for (int i = offset; i < offset + result; i++) {
   b[i] = (byte) Character.toLowerCase((char) b[i]);
  }
  return result;
 }
}

Client

package com.structural.decorator;

import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

public class DecoratorClient {
 public static void main(String[] args) throws IOException {
  int c;
  try {
   InputStream in = new InputStreamDecorator(new BufferedInputStream(
     new FileInputStream(“decorator.txt”)));
   while ((c = in.read()) >= 0) {
    System.out.print((char) c);
   }
   in.close();
  } catch (IOException e) {
   e.printStackTrace();
  }
 }
}

Decorator Pattern Vs Adapter

Adapter and Decorator’s similarity?

  • They both wrap objects at run-time
  • They both delegate requests to their wrapped objects

Adapter and Decorator are different?

  • Adapter converts one interface into another while maintaining functionality (extends Target, compose Adaptee)
  • Decorator leaves the interface alone but adds new functionality (extends and compose Object to decorate)
  • Decorators are designed to be “stacked”; that’s less likely to occur with adapter

Should Read: Adapter Pattern

Download Code: Decorator.zip

Please share your feedback/query.

One Response to Decorator Pattern

  1. I like this blog very much so much superb info.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: