Skip to content
Low Level Design Mastery Logo
LowLevelDesign Mastery

Bridge Pattern

Separate abstraction from implementation - build flexible systems that can evolve independently!

Now let’s explore the Bridge Pattern - a powerful structural design pattern that decouples abstraction from implementation.

Imagine you’re building a remote control for your TV. You want to support different types of TVs (Samsung, Sony, LG) and different types of remotes (Basic, Advanced, Smart). Without Bridge Pattern, you’d need a class for every combination (BasicSamsungRemote, AdvancedSamsungRemote, SmartSonyRemote, etc.) - that’s a lot of classes! The Bridge Pattern solves this by separating the remote (abstraction) from the TV (implementation).

The Bridge Pattern decouples an abstraction from its implementation so that the two can vary independently. It uses composition instead of inheritance to bridge the abstraction and implementation.

The Bridge Pattern is useful when:

  1. You want to avoid permanent binding - Between abstraction and implementation
  2. Abstraction and implementation should be extensible - Independently by subclassing
  3. Changes in implementation - Should not affect clients
  4. Hide implementation details - From clients
  5. Multiple implementations - Need to share the same abstraction

What Happens If We Don’t Use Bridge Pattern?

Section titled “What Happens If We Don’t Use Bridge Pattern?”

Without the Bridge Pattern, you might:

  • Exponential class explosion - Need classes for every combination (MxN classes)
  • Tight coupling - Abstraction and implementation are tightly bound
  • Hard to extend - Adding new abstraction or implementation requires many changes
  • Violate Open/Closed Principle - Need to modify existing code for new combinations
  • Code duplication - Similar code repeated across multiple classes

Let’s start with a super simple example that anyone can understand!

Diagram

Here’s how the Bridge Pattern works in practice - showing how abstraction and implementation interact:

sequenceDiagram
    participant Client
    participant BasicRemote as BasicRemote (Abstraction)
    participant SamsungTV as SamsungTV (Implementation)
    
    Client->>BasicRemote: power_on()
    activate BasicRemote
    BasicRemote->>SamsungTV: turn_on()
    activate SamsungTV
    SamsungTV-->>BasicRemote: TV turned on
    deactivate SamsungTV
    BasicRemote-->>Client: Success
    deactivate BasicRemote
    
    Note over Client,SamsungTV: Abstraction (Remote) uses<br/>Implementation (TV) through bridge!
    
    Client->>BasicRemote: volume_up()
    activate BasicRemote
    BasicRemote->>SamsungTV: set_volume(current + 1)
    activate SamsungTV
    SamsungTV-->>BasicRemote: Volume increased
    deactivate SamsungTV
    BasicRemote-->>Client: Volume: 5
    deactivate BasicRemote

You’re building a remote control system. You have different types of remotes (Basic, Advanced) and different types of TVs (Samsung, Sony). Without Bridge Pattern:

Problems:

  • Exponential class explosion - M remotes × N TVs = M×N classes
  • Code duplication - Same remote logic repeated for each TV
  • Hard to extend - Adding new remote or TV requires many new classes
  • Violates Open/Closed Principle
classDiagram
    class RemoteControl {
        <<abstraction>>
        -tv: TV
        +power_on() void
        +power_off() void
        +volume_up() void
        +volume_down() void
    }
    class BasicRemote {
        +power_on() void
        +power_off() void
        +volume_up() void
        +volume_down() void
    }
    class AdvancedRemote {
        +power_on() void
        +power_off() void
        +volume_up() void
        +volume_down() void
        +mute() void
    }
    class TV {
        <<interface>>
        +turn_on() void
        +turn_off() void
        +set_volume(int) void
    }
    class SamsungTV {
        +turn_on() void
        +turn_off() void
        +set_volume(int) void
    }
    class SonyTV {
        +turn_on() void
        +turn_off() void
        +set_volume(int) void
    }
    
    RemoteControl <|-- BasicRemote : extends
    RemoteControl <|-- AdvancedRemote : extends
    RemoteControl --> TV : has (bridge)
    TV <|.. SamsungTV : implements
    TV <|.. SonyTV : implements
    
    note for RemoteControl "Abstraction - what user interacts with"
    note for TV "Implementation - how it actually works"

Real-World Software Example: Shape Rendering System

Section titled “Real-World Software Example: Shape Rendering System”

Now let’s see a realistic software example - a graphics system that needs to render different shapes using different rendering engines.

You’re building a graphics application that needs to render shapes (Circle, Rectangle) using different rendering engines (Vector, Raster). Without Bridge Pattern:

Problems:

  • Exponential class explosion - M shapes × N renderers = M×N classes
  • Hard to extend - Adding new shape or renderer requires many classes
  • Code duplication - Similar rendering logic repeated

The Bridge Pattern is typically implemented using composition (Object Bridge), but there are considerations:

Uses composition - abstraction contains reference to implementation:

Pros: Flexible, can change implementation at runtime
Cons: Requires implementation instance


Use Bridge Pattern when:

You want to avoid permanent binding - Between abstraction and implementation
Abstraction and implementation should vary independently - By subclassing
Changes in implementation - Should not affect clients
Hide implementation details - From clients
Multiple implementations - Need to share the same abstraction
Runtime binding - Want to switch implementations at runtime

Don’t use Bridge Pattern when:

Simple one-to-one relationship - If abstraction and implementation are tightly coupled
Performance critical - Bridge adds indirection (usually negligible)
Over-engineering - Don’t add complexity for simple cases
Abstraction is stable - If abstraction rarely changes, direct inheritance might be simpler



  1. Decoupling - Abstraction and implementation are separated
  2. Independent Variation - Can vary abstraction and implementation independently
  3. No Class Explosion - M abstractions + N implementations = M + N classes (not M×N)
  4. Runtime Binding - Can switch implementations at runtime
  5. Open/Closed Principle - Open for extension, closed for modification
  6. Hide Implementation - Implementation details hidden from clients

Bridge Pattern is a structural design pattern that decouples an abstraction from its implementation so that the two can vary independently. It uses composition to bridge the abstraction and implementation.

  • Avoid class explosion - M abstractions × N implementations = M×N classes without Bridge
  • Independent variation - Change abstraction without changing implementation
  • Runtime binding - Switch implementations at runtime
  • Decoupling - Separate what you use from how it works
  • Open/Closed Principle - Open for extension, closed for modification
  1. Define implementation interface - How things work
  2. Implement concrete classes - Different implementations
  3. Define abstraction - What user interacts with
  4. Bridge them - Abstraction contains reference to implementation
  5. Extend independently - Add new abstractions or implementations independently
Abstraction → Implementation Interface → Concrete Implementation
  • Abstraction - What user interacts with (e.g., RemoteControl)
  • Implementation Interface - How things work (e.g., TV interface)
  • Concrete Implementation - Actual implementation (e.g., SamsungTV, SonyTV)
  • Bridge - Composition link between abstraction and implementation
class Implementation:
def operation(self): pass
class Abstraction:
def __init__(self, impl: Implementation):
self.impl = impl # Bridge
def operation(self):
return self.impl.operation()

✅ Avoid permanent binding between abstraction and implementation
Abstraction and implementation should vary independently
✅ Multiple implementations need to share same abstraction
✅ Want runtime binding
✅ Facing class explosion (M×N problem)

❌ Simple one-to-one relationship
❌ Performance critical (adds indirection)
❌ Over-engineering simple cases
Abstraction is stable

  • Bridge Pattern = Separates abstraction from implementation
  • Abstraction = What user interacts with
  • Implementation = How it actually works
  • Bridge = Composition link between them
  • Benefit = Independent variation, no class explosion
  • Use Case = When you have M abstractions and N implementations
class Implementation:
def operation(self): pass
class Abstraction:
def __init__(self, impl: Implementation):
self.impl = impl
def operation(self):
return self.impl.operation()
# Usage
impl = ConcreteImplementation()
abstraction = ConcreteAbstraction(impl)
abstraction.operation()
  • Bridge Pattern separates abstraction from implementation
  • It uses composition, not inheritance
  • It prevents class explosion (M×N → M+N)
  • Use it when you need independent variation
  • It’s about decoupling, not just wrapping!

What to say:

“Bridge Pattern is a structural design pattern that decouples an abstraction from its implementation so that the two can vary independently. It uses composition to bridge the abstraction and implementation, preventing class explosion.”

Why it matters:

  • Shows you understand the fundamental purpose
  • Demonstrates knowledge of when to use it
  • Indicates you can explain concepts clearly

Must mention:

  • Avoid class explosion - M abstractions × N implementations = M×N classes
  • Independent variation - Want to change abstraction without changing implementation
  • Runtime binding - Want to switch implementations at runtime
  • Decoupling - Separate what you use from how it works

Example scenario to give:

“I’d use Bridge Pattern when building a graphics system with different shapes (Circle, Rectangle) and different rendering engines (Vector, Raster). Without Bridge, I’d need Circle×Vector, Circle×Raster, Rectangle×Vector, Rectangle×Raster = 4 classes. With Bridge, I need 2 shapes + 2 renderers = 4 classes, but they can vary independently.”

Must discuss:

  • Bridge: Planned separation, abstraction and implementation vary independently
  • Adapter: Reactive solution, makes incompatible interfaces compatible
  • Key difference: Bridge is planned, Adapter is reactive

Example to give:

“Bridge Pattern is used when you plan to separate abstraction from implementation from the start. Adapter Pattern is used when you have existing incompatible interfaces that need to work together. Bridge is about design, Adapter is about compatibility.”

Benefits to mention:

  • No class explosion - M + N instead of M×N classes
  • Independent variation - Change abstraction or implementation independently
  • Runtime binding - Switch implementations at runtime
  • Decoupling - Abstraction and implementation are separate
  • Open/Closed Principle - Open for extension, closed for modification

Trade-offs to acknowledge:

  • Complexity - Adds a layer of indirection
  • Performance - Small overhead (usually negligible)
  • Over-engineering risk - Can be overkill for simple cases

Q: “What’s the difference between Bridge Pattern and Adapter Pattern?”

A:

“Bridge Pattern is a planned separation of abstraction from implementation, allowing them to vary independently. Adapter Pattern is a reactive solution that makes incompatible interfaces compatible. Bridge is about design and flexibility, Adapter is about compatibility and integration.”

Q: “When would you use Bridge vs direct inheritance?”

A:

“I use Bridge when I need independent variation of abstraction and implementation. If I have M types of remotes and N types of TVs, inheritance would require M×N classes. Bridge requires only M + N classes. I use direct inheritance when there’s a stable one-to-one relationship.”

Q: “How does Bridge Pattern relate to SOLID principles?”

A:

“Bridge Pattern primarily supports the Open/Closed Principle - you can extend functionality (add new abstractions or implementations) without modifying existing code. It also supports Single Responsibility Principle by separating abstraction concerns from implementation concerns. Additionally, it helps with Dependency Inversion Principle by having abstractions depend on implementation interfaces rather than concrete implementations.”

Before your interview, make sure you can:

  • Define Bridge Pattern clearly in one sentence
  • Explain when to use it (with examples showing class explosion)
  • Describe Bridge vs Adapter Pattern
  • Implement Bridge Pattern from scratch
  • Compare with other structural patterns (Adapter, Decorator)
  • List benefits and trade-offs
  • Identify common mistakes
  • Give 2-3 real-world examples
  • Connect to SOLID principles
  • Discuss when NOT to use it
  • Explain M×N class explosion problem

Remember: Bridge Pattern is about separating abstraction from implementation - allowing them to vary independently and preventing class explosion! 🌉