Friday, 20 June 2025

 

Decorator Pattern

The Decorator Pattern is a structural design pattern that lets you attach additional responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality.

In Java, the Decorator Pattern is used to wrap objects in decorator classes that add new behaviors or responsibilities without changing the original object's code.

 

Intent

  • Attach additional responsibilities to an object dynamically.
  • Provide a flexible alternative to subclassing for extending functionality.
  • Keep the core object and its extensions separate.
  • Enable adding features transparently to clients.

Participants

The main participants in the Decorator Pattern are:

a. Component (interface or abstract class)

  • Defines the interface for objects that can have responsibilities added to them dynamically.
  • Example: Text interface with getContent() method.

b. ConcreteComponent (implements Component)

  • The core object to which additional responsibilities can be attached.
  • Example: SimpleText class that implements Text.

c. Decorator (abstract class or interface implementing Component)

  • Maintains a reference to a Component object.
  • Implements the Component interface.
  • Delegates operations to the wrapped component.
  • Acts as a base class for concrete decorators.

d. ConcreteDecorator (extends Decorator)

  • Adds responsibilities to the component.
  • Overrides component methods to provide extra behavior.
  • Example: UpperCaseDecorator and StarDecorator.

 

Uml

 

 

How it Works

  • The client interacts with objects through the Component interface.
  • A ConcreteComponent is created, which implements the basic behavior.
  • To add functionality, a Decorator wraps the ConcreteComponent.
  • Multiple decorators can wrap the same component to combine behaviors.
  • Decorators forward requests to the wrapped component, adding extra processing before or after forwarding.

Benefits (Advantages)

  • Open/Closed Principle: You can add new behavior without modifying existing code.
  • Flexible extension: New functionality can be added at runtime.
  • Avoids an explosion of subclasses by combining decorators instead of subclassing.
  • Can wrap multiple decorators to compose complex behavior.
  • Transparent to the client — clients use decorated objects via the same interface.

Drawbacks (Disadvantages)

  • Can produce a large number of small classes.
  • The design can become complex if many decorators are stacked.
  • Debugging can be harder because of many layers of wrapping.
  • Slight performance overhead due to multiple levels of indirection.

Typical Use Cases in Java

  • Adding features to streams (java.io package uses Decorator pattern extensively: BufferedReader, InputStreamReader).
  • GUI frameworks for adding borders, scrollbars, or behaviors to components.
  • Adding responsibilities such as logging, caching, validation dynamically.
  • Adding filters or transformations to data streams or collections.

 

Real-world Example (Java IO)

Java’s IO library is a classic example of the Decorator Pattern:

  • InputStream is the Component.
  • FileInputStream is a ConcreteComponent.
  • BufferedInputStream is a Decorator adding buffering.
  • DataInputStream is another Decorator adding data-type reading.

You can wrap a FileInputStream inside a BufferedInputStream and then wrap that in a DataInputStream to combine functionalities dynamically.

InputStream file = new FileInputStream("file.txt");

InputStream buffer = new BufferedInputStream(file);

DataInputStream data = new DataInputStream(buffer);

 

int value = data.readInt();

Summary

Aspect

Description

Pattern Type

Structural

Purpose

Add responsibilities dynamically

Key Principle

Composition over inheritance

Key Benefit

Flexible, reusable, open to extension

Main Components

Component, ConcreteComponent, Decorator, ConcreteDecorator

Common Usage

Java IO, GUI component decoration

 

 

 

Example : -

Component

package decoratordesignpattern;

 

public interface Text {

               String getContent();

}

 

ConcreteComponent

 

 

package decoratordesignpattern;

 

public class SimpleText implements Text {

 

               private String content;

 

               public SimpleText(String content) {

                              super();

                              this.content = content;

               }

 

               @Override

               public String getContent() {

                              return content;

               }

 

}

 

 

Decorator

 

package decoratordesignpattern;

 

public abstract class TextDecorator implements Text {

 

               protected Text decoratedText;

 

               public TextDecorator(Text decoratedText) {

                              super();

                              this.decoratedText = decoratedText;

               }

 

               @Override

               public String getContent() {

                              return decoratedText.getContent();

               }

}

 

 

 

ConcreteDecorator

 

package decoratordesignpattern;

 

public class UpperCaseDecorator extends TextDecorator {

 

               public UpperCaseDecorator(Text decoratedText) {

                              super(decoratedText);

 

               }

 

               public String getContent() {

                              return decoratedText.getContent().toUpperCase();

               }

 

}

 

 

package decoratordesignpattern;

 

public class StarDecorator extends TextDecorator {

 

               public StarDecorator(Text decoratedText) {

                              super(decoratedText);

                              // TODO Auto-generated constructor stub

               }

 

               @Override

               public String getContent() {

                              return "*** " + decoratedText.getContent() + " ***";

               }

 

}

 

 

 

package decoratordesignpattern;

 

public class DecoratorDemo {

 

               public static void main(String[] args) {

 

                              Text myText = new SimpleText("Hello World!");

 

                              // Wrap with uppercase decorator

                              Text upper = new UpperCaseDecorator(myText);

                              System.out.println(upper.getContent()); // Output: HELLO, WORLD!

 

                              // Wrap with star decorator

                              Text starred = new StarDecorator(myText);

                              System.out.println(starred.getContent()); // Output: *** Hello, world! ***

 

                              // Combine decorators (starred + uppercase)

                              Text starredUpper = new StarDecorator(upper);

                              System.out.println(starredUpper.getContent()); // Output: *** HELLO, WORLD! ***

 

               }

}

 

 

 

o/p :-

HELLO WORLD!

*** Hello World! ***

*** HELLO WORLD! ***

 

 

 

 

 

 

 

 

 

 

 

 

 

No comments:

Post a Comment