MTI TEK
  • Home
  • About
  • LLMs
  • Docker
  • Kubernetes
  • Java
  • All Resources
Java Design Patterns | Decorator
  1. Overview and Definition
  2. Class Diagram
  3. Implementation Example
    • The Component Interface
    • The Concrete Component
    • The Base Decorator
    • The Concrete Decorators
    • Testing the Decorator Pattern

  1. Overview and Definition
    The Decorator pattern is a structural design pattern that allows behavior to be added to objects dynamically without altering their structure. It provides a flexible alternative to subclassing for extending functionality by wrapping objects in decorator classes.

    Key Components:
    • Component: Defines the interface for objects that can have responsibilities added to them dynamically.
    • Concrete Component: The original object to which additional responsibilities can be attached.
    • Decorator: Maintains a reference to a Component object and defines an interface that conforms to Component's interface.
    • Concrete Decorator: Adds specific responsibilities to the component by extending the Decorator class.
    • Client: Uses the Component interface to work with objects, whether they are decorated or not.

    Benefits:
    • Dynamic Behavior Addition: Allows adding responsibilities to objects at runtime without changing their classes or affecting other instances.
    • Flexible Alternative to Inheritance: Provides more flexibility than static inheritance by allowing behavior combinations that would require many subclasses.
  2. Class Diagram
    Decorator Pattern Components:
    • Component: Logger interface - defines the interface for objects that can be decorated.
    • Concrete Component: FileLogger class - the original object that can have responsibilities added.
    • Base Decorator: LoggerDecorator class - maintains reference to Component and provides delegation.
    • Concrete Decorators: TimestampLogger, EncryptionLogger - add specific functionality to the component.
    ┌─────────────────────────────┐
    │       <<interface>>         │
    │          Logger             │  ← Component
    ├─────────────────────────────┤
    │ + log(String): void         │
    └─────────────────────────────┘
                  △
                  │ implements
                  │
    ┌─────────────────────────────┐
    │        FileLogger           │  ← Concrete Component
    ├─────────────────────────────┤
    │ + log(String): void         │
    └─────────────────────────────┘
    
    
    ┌─────────────────────────────┐
    │       <<abstract>>          │
    │      LoggerDecorator        │  ← Base Decorator
    ├─────────────────────────────┤
    │ - logger: Logger            │
    │ + LoggerDecorator(Logger)   │
    │ + log(String): void         │
    └─────────────────────────────┘
                  △
                  │ extends
                  │
    ┌─────────────────┬───────────────────┐
    │ TimestampLogger │ EncryptionLogger  │  ← Concrete Decorators
    ├─────────────────┼───────────────────┤
    │+ log(String)    │+ log(String)      │
    └─────────────────┴───────────────────┘
    
  3. Implementation Example
    • The Component Interface:
      The Component interface defines the contract for objects that can have responsibilities added to them dynamically. All concrete components and decorators implement this interface.
      public interface Logger {
          void log(String message);
      }
    • The Concrete Component:
      The Concrete Component is the original object that provides basic functionality. Decorators will wrap this object to add additional behavior.
      public class FileLogger implements Logger {
          public void log(String message) {
              System.out.println("FileLogger: " + message);
          }
      }
    • The Base Decorator:
      The Base Decorator class implements the Component interface and maintains a reference to another Component object. It delegates calls to the wrapped component and serves as the base for concrete decorators.
      public abstract class LoggerDecorator implements Logger {
          protected Logger logger;
      
          public LoggerDecorator(Logger logger) {
              this.logger = logger;
          }
      
          public void log(String message) {
              logger.log(message);
          }
      }
    • The Concrete Decorators:
      Concrete Decorators extend the Base Decorator and add specific functionality before or after delegating to the wrapped component. Multiple decorators can be chained together.

      Timestamp Decorator:
      public class TimestampLogger extends LoggerDecorator {
          public TimestampLogger(Logger logger) {
              super(logger);
          }
      
          @Override
          public void log(String message) {
              String timestampedMessage = "[" + java.time.LocalDateTime.now() + "] " + message;
              super.log(timestampedMessage);
          }
      }
      Encryption Decorator:
      public class EncryptionLogger extends LoggerDecorator {
          public EncryptionLogger(Logger logger) {
              super(logger);
          }
      
          @Override
          public void log(String message) {
              String encryptedMessage = "ENCRYPTED[" + message + "]";
              super.log(encryptedMessage);
          }
      }
    • Testing the Decorator Pattern:
      The client code demonstrates how decorators can be applied individually or in combination to add functionality dynamically. Decorators can be stacked to create complex behavior combinations.
      public class DecoratorPatternTest {
          public static void main(String[] args) {
              // Create the base component
              Logger fileLogger = new FileLogger();
              
              // Example 1: Basic logging
              System.out.println("Basic Logging");
              fileLogger.log("Simple log message");
              
              // Example 2: Add timestamp decoration
              System.out.println("With Timestamp");
              Logger timestampLogger = new TimestampLogger(fileLogger);
              timestampLogger.log("Message with timestamp");
              
              // Example 3: Add encryption decoration
              System.out.println("With Encryption");
              Logger encryptionLogger = new EncryptionLogger(fileLogger);
              encryptionLogger.log("Secret message");
              
              // Example 4: Chain multiple decorators
              System.out.println("With Both Decorators");
              Logger decoratedLogger = new EncryptionLogger(new TimestampLogger(fileLogger));
              decoratedLogger.log("Fully decorated message");
          }
      }
© 2025 mtitek