MTI TEK
  • Home
  • About
  • LLMs
  • Docker
  • Kubernetes
  • Java
  • All Resources
Java Design Patterns | Bridge
  1. Overview and Definition
  2. Class Diagram
  3. Implementation Example
    • The Implementor Interface
    • The Concrete Implementors
    • The Abstraction
    • The Refined Abstractions
    • Testing the Bridge Pattern

  1. Overview and Definition
    The Bridge pattern is a structural design pattern that decouples an abstraction from its implementation, allowing both to vary independently. This pattern is useful when you want to share an implementation among multiple objects or when you want to switch implementations at runtime.

    Key Components:
    • Abstraction: Defines the abstraction's interface and maintains a reference to an object of type Implementor. It delegates the actual work to the implementor.
    • Refined Abstraction: Extends the interface defined by Abstraction and provides different variations or enhanced functionality.
    • Implementor: Defines the interface for implementation classes. This interface doesn't need to correspond exactly to the Abstraction's interface.
    • Concrete Implementor: Implements the Implementor interface and defines the concrete implementation details.
    • Client: Uses the Abstraction interface to work with objects, unaware of the specific implementation being used.

    Benefits:
    • Decoupling: Separates the abstraction from its implementation, allowing both to evolve independently without affecting each other.
    • Improved Maintainability: Changes to implementation details don't affect the abstraction layer and vice versa.
  2. Class Diagram
    Bridge Pattern Components:
    • Abstraction: MessageSender interface - defines the high-level interface for sending messages.
    • Refined Abstractions: EmailSender, SMSSender classes - specific implementations of message sending.
    • Implementor: Logger interface - defines the interface for logging implementations.
    • Concrete Implementors: FileLogger, ConsoleLogger classes - specific logging implementations.
    ┌─────────────────────────────┐
    │       <<interface>>         │
    │      MessageSender          │  ← Abstraction
    ├─────────────────────────────┤
    │ + sendMessage(): void       │
    └─────────────────────────────┘
                  △
                  │ implements
                  │
    ┌─────────────────┬───────────────────┐
    │  EmailSender    │   SMSSender       │  ← Refined Abstractions
    ├─────────────────┼───────────────────┤
    │- logger: Logger │- logger: Logger   │
    │+ sendMessage()  │+ sendMessage()    │
    └─────────────────┴───────────────────┘
           │                    │
           │ uses               │ uses
           ▼                    ▼
    ┌─────────────────────────────┐
    │       <<interface>>         │
    │          Logger             │  ← Implementor
    ├─────────────────────────────┤
    │ + log(String): void         │
    └─────────────────────────────┘
                  △
                  │ implements
                  │
    ┌─────────────────┬───────────────────┐
    │   FileLogger    │  ConsoleLogger    │  ← Concrete Implementors
    ├─────────────────┼───────────────────┤
    │+ log(String)    │+ log(String)      │
    └─────────────────┴───────────────────┘
    
  3. Implementation Example
    • The Implementor Interface:
      The Implementor interface defines the low-level operations that concrete implementors will provide. This interface focuses on the implementation details rather than the business logic.
      public interface Logger {
          void log(String message);
      }
    • The Concrete Implementors:
      Concrete Implementors provide specific implementations of the Implementor interface. Each implementor handles the low-level details in its own way.

      File Logger Implementation:
      public class FileLogger implements Logger {
          public void log(String message) {
              System.out.println("FileLogger: Writing to file - " + message);
          }
      }
      Console Logger Implementation:
      public class ConsoleLogger implements Logger {
          public void log(String message) {
              System.out.println("ConsoleLogger: Writing to console - " + message);
          }
      }
    • The Abstraction:
      The Abstraction interface defines the high-level interface that clients will use. It focuses on the business logic rather than implementation details.
      public interface MessageSender {
          void sendMessage();
      }
    • The Refined Abstractions:
      Refined Abstractions extend the Abstraction interface and use the Implementor to accomplish their tasks. They bridge the gap between high-level operations and low-level implementations.

      Email Sender:
      public class EmailSender implements MessageSender {
          private Logger logger;
      
          public EmailSender(Logger logger) {
              this.logger = logger;
          }
      
          public void sendMessage() {
              String message = "Email sent successfully";
              logger.log(message);
          }
      }
      SMS Sender:
      public class SMSSender implements MessageSender {
          private Logger logger;
      
          public SMSSender(Logger logger) {
              this.logger = logger;
          }
      
          public void sendMessage() {
              String message = "SMS sent successfully";
              logger.log(message);
          }
      }
    • Testing the Bridge Pattern:
      The client code demonstrates how the Bridge pattern allows abstractions and implementations to vary independently. Different combinations can be created at runtime.
      public class BridgePatternTest {
          public static void main(String[] args) {
              // Create different logger implementations
              Logger fileLogger = new FileLogger();
              Logger consoleLogger = new ConsoleLogger();
      
              // Example 1: Email with File Logging
              MessageSender emailWithFileLog = new EmailSender(fileLogger);
              emailWithFileLog.sendMessage();
      
              // Example 2: Email with Console Logging
              MessageSender emailWithConsoleLog = new EmailSender(consoleLogger);
              emailWithConsoleLog.sendMessage();
      
              // Example 3: SMS with File Logging
              MessageSender smsWithFileLog = new SMSSender(fileLogger);
              smsWithFileLog.sendMessage();
      
              // Example 4: SMS with Console Logging
              MessageSender smsWithConsoleLog = new SMSSender(consoleLogger);
              smsWithConsoleLog.sendMessage();
          }
      }
© 2025 mtitek