Skip to content

Latest commit

 

History

History
79 lines (50 loc) · 2.57 KB

File metadata and controls

79 lines (50 loc) · 2.57 KB

Decorator Pattern

Overview

The Decorator Pattern attaches additional responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality.

Pattern Structure

The Decorator Pattern uses composition to wrap objects with new behaviors. Decorators have the same supertype as the objects they decorate, allowing decorated objects to be used in place of the original object.

Key Concepts

  • Component: The interface or abstract class defining the object that can have responsibilities added to it
  • ConcreteComponent: The object to which additional responsibilities can be attached
  • Decorator: Abstract class that wraps a Component and has the same interface
  • ConcreteDecorator: Adds responsibilities to the component

Examples

CoffeeExample

Demonstrates the classic Starbucks coffee ordering system where beverages can be decorated with condiments (milk, mocha, whip, etc.).

See the CoffeeExample README for details.

CustomIO

Shows how to create custom I/O decorators in Java, similar to how Java's I/O classes use the Decorator Pattern.

See the CustomIO README for details.

How to Compile

From the parent directory of DecoratorPattern:

javac -d out DecoratorPattern/CoffeeExample/*.java

Or for the custom I/O example:

javac -d out DecoratorPattern/CustomIO/*.java

How to Run

java -cp out DecoratorPattern.CoffeeExample.StarbuzzCoffee

Or for the custom I/O example:

java -cp out DecoratorPattern.CustomIO.InputTest

Benefits of the Decorator Pattern

  • Flexibility: More flexible than static inheritance
  • Runtime Enhancement: Can add or remove responsibilities at runtime
  • Avoids Feature-Laden Classes: Instead of one class with all features, use multiple decorators
  • Open/Closed Principle: Classes are open for extension but closed for modification
  • Single Responsibility: Each decorator handles one responsibility

When to Use

Use the Decorator Pattern when:

  • You need to add responsibilities to individual objects dynamically and transparently
  • Responsibilities can be withdrawn
  • Extension by subclassing is impractical (would result in too many subclasses)
  • You want to add functionality without affecting other objects

Real-World Examples

  • Java I/O Classes: BufferedInputStream, LineNumberInputStream wrap other streams
  • GUI Components: Scrollbars, borders can be added to windows
  • Web Frameworks: Middleware/filters that wrap HTTP requests/responses