Skip to content

Bridge Pattern

Category: Structural Pattern

Overview

Decouple an abstraction from its implementation so that the two can vary independently. This pattern uses composition over inheritance to separate the interface from the implementation, allowing both to be extended independently without affecting each other.

Usage Guidelines

Use when:

  • Want to avoid permanent binding between abstraction and implementation
  • Both abstraction and implementation should be extended independently
  • Need to switch implementations at runtime
  • Multiple implementations of abstraction exist

Avoid when:

  • Only one implementation exists
  • Implementation doesn't vary
  • Simple inheritance suffices
  • Extra indirection is unacceptable for performance

Implementation

from __future__ import annotations
from abc import ABC, abstractmethod

# Implementation Interface
class Renderer(ABC):
    """Abstract implementation interface for rendering."""

    @abstractmethod
    def render_circle(self, radius: float) -> str:
        """Render a circle."""
        pass

    @abstractmethod
    def render_square(self, side: float) -> str:
        """Render a square."""
        pass

# Concrete Implementations
class VectorRenderer(Renderer):
    """Concrete implementation for vector rendering."""

    def render_circle(self, radius: float) -> str:
        """Render circle as vector."""
        return f"Drawing circle with radius {radius} as vector"

    def render_square(self, side: float) -> str:
        """Render square as vector."""
        return f"Drawing square with side {side} as vector"

class RasterRenderer(Renderer):
    """Concrete implementation for raster rendering."""

    def render_circle(self, radius: float) -> str:
        """Render circle as raster."""
        return f"Drawing circle with radius {radius} as pixels"

    def render_square(self, side: float) -> str:
        """Render square as raster."""
        return f"Drawing square with side {side} as pixels"

# Abstraction
class Shape(ABC):
    """Abstract shape class using bridge to renderer."""

    def __init__(self, renderer: Renderer) -> None:
        """Initialize shape with a renderer."""
        self.renderer = renderer

    @abstractmethod
    def draw(self) -> str:
        """Draw the shape."""
        pass

    @abstractmethod
    def resize(self, factor: float) -> None:
        """Resize the shape."""
        pass

# Refined Abstractions
class Circle(Shape):
    """Concrete circle shape."""

    def __init__(self, renderer: Renderer, radius: float = 5.0) -> None:
        """Initialize circle."""
        super().__init__(renderer)
        self.radius = radius

    def draw(self) -> str:
        """Draw circle using renderer."""
        return self.renderer.render_circle(self.radius)

    def resize(self, factor: float) -> None:
        """Resize circle."""
        self.radius *= factor

class Square(Shape):
    """Concrete square shape."""

    def __init__(self, renderer: Renderer, side: float = 5.0) -> None:
        """Initialize square."""
        super().__init__(renderer)
        self.side = side

    def draw(self) -> str:
        """Draw square using renderer."""
        return self.renderer.render_square(self.side)

    def resize(self, factor: float) -> None:
        """Resize square."""
        self.side *= factor

Usage

# Create shapes with different renderers
circle_vector = Circle(VectorRenderer(), 5.0)
print(circle_vector.draw())  # Drawing circle with radius 5.0 as vector

circle_raster = Circle(RasterRenderer(), 5.0)
print(circle_raster.draw())  # Drawing circle with radius 5.0 as pixels

square_vector = Square(VectorRenderer(), 10.0)
print(square_vector.draw())  # Drawing square with side 10.0 as vector

# Resize and redraw
circle_vector.resize(2.0)
print(circle_vector.draw())  # Drawing circle with radius 10.0 as vector

Trade-offs

Benefits:

  1. Abstraction and implementation can vary independently
  2. Implementation can be selected or switched at runtime
  3. Isolates platform-specific code
  4. New abstractions and implementations without changing existing code (Open/Closed Principle)

Drawbacks:

  1. Adds complexity with additional abstractions
  2. Extra layer of indirection
  3. Can be hard to design proper abstraction/implementation split
  4. Too complex for simple scenarios

Real-World Examples

  • GUI frameworks separating GUI from platform-specific rendering
  • Database drivers with abstract operations from specific implementations
  • Graphics systems separating shapes from rendering methods
  • Device drivers separating operations from hardware implementations
  • Abstract Factory
  • Adapter
  • State

API Reference

design_patterns.structural.bridge

Bridge Pattern Module

The Bridge pattern decouples an abstraction from its implementation so that the two can vary independently. It uses composition over inheritance to separate the interface from the implementation, allowing both to be extended independently.

Example

Drawing shapes with different rendering implementations:

# Create a circle with vector rendering
circle = Circle(VectorRenderer())
circle.draw()  # Draws circle using vector graphics

# Create a square with raster rendering
square = Square(RasterRenderer())
square.draw()  # Draws square using raster graphics

AdvancedRemoteControl

Bases: RemoteControl

Extended remote control with additional features.

Source code in src/design_patterns/structural/bridge.py
class AdvancedRemoteControl(RemoteControl):
    """Extended remote control with additional features."""

    def mute(self) -> str:
        """Mute the device.

        Returns:
            Status message.
        """
        self.device.set_volume(0)
        return "Device muted"

mute()

Mute the device.

Returns:

Type Description
str

Status message.

Source code in src/design_patterns/structural/bridge.py
def mute(self) -> str:
    """Mute the device.

    Returns:
        Status message.
    """
    self.device.set_volume(0)
    return "Device muted"

Circle

Bases: Shape

Concrete circle shape.

Source code in src/design_patterns/structural/bridge.py
class Circle(Shape):
    """Concrete circle shape."""

    def __init__(self, renderer: Renderer, radius: float = 5.0) -> None:
        """Initialize circle.

        Args:
            renderer: The renderer to use.
            radius: Circle radius.
        """
        super().__init__(renderer)
        self.radius = radius

    def draw(self) -> str:
        """Draw circle using renderer.

        Returns:
            Drawing result.
        """
        return self.renderer.render_circle(self.radius)

    def resize(self, factor: float) -> None:
        """Resize circle.

        Args:
            factor: Resize factor.
        """
        self.radius *= factor

__init__(renderer, radius=5.0)

Initialize circle.

Parameters:

Name Type Description Default
renderer Renderer

The renderer to use.

required
radius float

Circle radius.

5.0
Source code in src/design_patterns/structural/bridge.py
def __init__(self, renderer: Renderer, radius: float = 5.0) -> None:
    """Initialize circle.

    Args:
        renderer: The renderer to use.
        radius: Circle radius.
    """
    super().__init__(renderer)
    self.radius = radius

draw()

Draw circle using renderer.

Returns:

Type Description
str

Drawing result.

Source code in src/design_patterns/structural/bridge.py
def draw(self) -> str:
    """Draw circle using renderer.

    Returns:
        Drawing result.
    """
    return self.renderer.render_circle(self.radius)

resize(factor)

Resize circle.

Parameters:

Name Type Description Default
factor float

Resize factor.

required
Source code in src/design_patterns/structural/bridge.py
def resize(self, factor: float) -> None:
    """Resize circle.

    Args:
        factor: Resize factor.
    """
    self.radius *= factor

Device

Bases: ABC

Abstract device interface.

Source code in src/design_patterns/structural/bridge.py
class Device(ABC):
    """Abstract device interface."""

    @abstractmethod
    def is_enabled(self) -> bool:
        """Check if device is enabled.

        Returns:
            True if enabled.
        """
        pass

    @abstractmethod
    def enable(self) -> None:
        """Enable the device."""
        pass

    @abstractmethod
    def disable(self) -> None:
        """Disable the device."""
        pass

    @abstractmethod
    def get_volume(self) -> int:
        """Get current volume.

        Returns:
            Volume level.
        """
        pass

    @abstractmethod
    def set_volume(self, percent: int) -> None:
        """Set volume.

        Args:
            percent: Volume percentage.
        """
        pass

disable() abstractmethod

Disable the device.

Source code in src/design_patterns/structural/bridge.py
@abstractmethod
def disable(self) -> None:
    """Disable the device."""
    pass

enable() abstractmethod

Enable the device.

Source code in src/design_patterns/structural/bridge.py
@abstractmethod
def enable(self) -> None:
    """Enable the device."""
    pass

get_volume() abstractmethod

Get current volume.

Returns:

Type Description
int

Volume level.

Source code in src/design_patterns/structural/bridge.py
@abstractmethod
def get_volume(self) -> int:
    """Get current volume.

    Returns:
        Volume level.
    """
    pass

is_enabled() abstractmethod

Check if device is enabled.

Returns:

Type Description
bool

True if enabled.

Source code in src/design_patterns/structural/bridge.py
@abstractmethod
def is_enabled(self) -> bool:
    """Check if device is enabled.

    Returns:
        True if enabled.
    """
    pass

set_volume(percent) abstractmethod

Set volume.

Parameters:

Name Type Description Default
percent int

Volume percentage.

required
Source code in src/design_patterns/structural/bridge.py
@abstractmethod
def set_volume(self, percent: int) -> None:
    """Set volume.

    Args:
        percent: Volume percentage.
    """
    pass

Radio

Bases: Device

Concrete radio device.

Source code in src/design_patterns/structural/bridge.py
class Radio(Device):
    """Concrete radio device."""

    def __init__(self) -> None:
        """Initialize radio."""
        self._enabled = False
        self._volume = 30

    def is_enabled(self) -> bool:
        """Check if radio is on.

        Returns:
            True if on.
        """
        return self._enabled

    def enable(self) -> None:
        """Turn radio on."""
        self._enabled = True

    def disable(self) -> None:
        """Turn radio off."""
        self._enabled = False

    def get_volume(self) -> int:
        """Get radio volume.

        Returns:
            Volume level.
        """
        return self._volume

    def set_volume(self, percent: int) -> None:
        """Set radio volume.

        Args:
            percent: Volume percentage.
        """
        self._volume = max(0, min(100, percent))

__init__()

Initialize radio.

Source code in src/design_patterns/structural/bridge.py
def __init__(self) -> None:
    """Initialize radio."""
    self._enabled = False
    self._volume = 30

disable()

Turn radio off.

Source code in src/design_patterns/structural/bridge.py
def disable(self) -> None:
    """Turn radio off."""
    self._enabled = False

enable()

Turn radio on.

Source code in src/design_patterns/structural/bridge.py
def enable(self) -> None:
    """Turn radio on."""
    self._enabled = True

get_volume()

Get radio volume.

Returns:

Type Description
int

Volume level.

Source code in src/design_patterns/structural/bridge.py
def get_volume(self) -> int:
    """Get radio volume.

    Returns:
        Volume level.
    """
    return self._volume

is_enabled()

Check if radio is on.

Returns:

Type Description
bool

True if on.

Source code in src/design_patterns/structural/bridge.py
def is_enabled(self) -> bool:
    """Check if radio is on.

    Returns:
        True if on.
    """
    return self._enabled

set_volume(percent)

Set radio volume.

Parameters:

Name Type Description Default
percent int

Volume percentage.

required
Source code in src/design_patterns/structural/bridge.py
def set_volume(self, percent: int) -> None:
    """Set radio volume.

    Args:
        percent: Volume percentage.
    """
    self._volume = max(0, min(100, percent))

RasterRenderer

Bases: Renderer

Concrete implementation for raster rendering.

Source code in src/design_patterns/structural/bridge.py
class RasterRenderer(Renderer):
    """Concrete implementation for raster rendering."""

    def render_circle(self, radius: float) -> str:
        """Render circle as raster.

        Args:
            radius: Circle radius.

        Returns:
            Raster rendering result.
        """
        return f"Drawing circle with radius {radius} as pixels"

    def render_square(self, side: float) -> str:
        """Render square as raster.

        Args:
            side: Square side length.

        Returns:
            Raster rendering result.
        """
        return f"Drawing square with side {side} as pixels"

render_circle(radius)

Render circle as raster.

Parameters:

Name Type Description Default
radius float

Circle radius.

required

Returns:

Type Description
str

Raster rendering result.

Source code in src/design_patterns/structural/bridge.py
def render_circle(self, radius: float) -> str:
    """Render circle as raster.

    Args:
        radius: Circle radius.

    Returns:
        Raster rendering result.
    """
    return f"Drawing circle with radius {radius} as pixels"

render_square(side)

Render square as raster.

Parameters:

Name Type Description Default
side float

Square side length.

required

Returns:

Type Description
str

Raster rendering result.

Source code in src/design_patterns/structural/bridge.py
def render_square(self, side: float) -> str:
    """Render square as raster.

    Args:
        side: Square side length.

    Returns:
        Raster rendering result.
    """
    return f"Drawing square with side {side} as pixels"

RemoteControl

Abstraction for remote control using bridge to device.

Source code in src/design_patterns/structural/bridge.py
class RemoteControl:
    """Abstraction for remote control using bridge to device."""

    def __init__(self, device: Device) -> None:
        """Initialize remote with a device.

        Args:
            device: The device to control.
        """
        self.device = device

    def toggle_power(self) -> str:
        """Toggle device power.

        Returns:
            Status message.
        """
        if self.device.is_enabled():
            self.device.disable()
            return "Device turned off"
        else:
            self.device.enable()
            return "Device turned on"

    def volume_up(self) -> str:
        """Increase volume.

        Returns:
            Status message.
        """
        current = self.device.get_volume()
        self.device.set_volume(current + 10)
        return f"Volume increased to {self.device.get_volume()}"

    def volume_down(self) -> str:
        """Decrease volume.

        Returns:
            Status message.
        """
        current = self.device.get_volume()
        self.device.set_volume(current - 10)
        return f"Volume decreased to {self.device.get_volume()}"

__init__(device)

Initialize remote with a device.

Parameters:

Name Type Description Default
device Device

The device to control.

required
Source code in src/design_patterns/structural/bridge.py
def __init__(self, device: Device) -> None:
    """Initialize remote with a device.

    Args:
        device: The device to control.
    """
    self.device = device

toggle_power()

Toggle device power.

Returns:

Type Description
str

Status message.

Source code in src/design_patterns/structural/bridge.py
def toggle_power(self) -> str:
    """Toggle device power.

    Returns:
        Status message.
    """
    if self.device.is_enabled():
        self.device.disable()
        return "Device turned off"
    else:
        self.device.enable()
        return "Device turned on"

volume_down()

Decrease volume.

Returns:

Type Description
str

Status message.

Source code in src/design_patterns/structural/bridge.py
def volume_down(self) -> str:
    """Decrease volume.

    Returns:
        Status message.
    """
    current = self.device.get_volume()
    self.device.set_volume(current - 10)
    return f"Volume decreased to {self.device.get_volume()}"

volume_up()

Increase volume.

Returns:

Type Description
str

Status message.

Source code in src/design_patterns/structural/bridge.py
def volume_up(self) -> str:
    """Increase volume.

    Returns:
        Status message.
    """
    current = self.device.get_volume()
    self.device.set_volume(current + 10)
    return f"Volume increased to {self.device.get_volume()}"

Renderer

Bases: ABC

Abstract implementation interface for rendering.

Source code in src/design_patterns/structural/bridge.py
class Renderer(ABC):
    """Abstract implementation interface for rendering."""

    @abstractmethod
    def render_circle(self, radius: float) -> str:
        """Render a circle.

        Args:
            radius: Circle radius.

        Returns:
            Rendering result.
        """
        pass

    @abstractmethod
    def render_square(self, side: float) -> str:
        """Render a square.

        Args:
            side: Square side length.

        Returns:
            Rendering result.
        """
        pass

render_circle(radius) abstractmethod

Render a circle.

Parameters:

Name Type Description Default
radius float

Circle radius.

required

Returns:

Type Description
str

Rendering result.

Source code in src/design_patterns/structural/bridge.py
@abstractmethod
def render_circle(self, radius: float) -> str:
    """Render a circle.

    Args:
        radius: Circle radius.

    Returns:
        Rendering result.
    """
    pass

render_square(side) abstractmethod

Render a square.

Parameters:

Name Type Description Default
side float

Square side length.

required

Returns:

Type Description
str

Rendering result.

Source code in src/design_patterns/structural/bridge.py
@abstractmethod
def render_square(self, side: float) -> str:
    """Render a square.

    Args:
        side: Square side length.

    Returns:
        Rendering result.
    """
    pass

Shape

Bases: ABC

Abstract shape class using bridge to renderer.

Source code in src/design_patterns/structural/bridge.py
class Shape(ABC):
    """Abstract shape class using bridge to renderer."""

    def __init__(self, renderer: Renderer) -> None:
        """Initialize shape with a renderer.

        Args:
            renderer: The renderer implementation to use.
        """
        self.renderer = renderer

    @abstractmethod
    def draw(self) -> str:
        """Draw the shape.

        Returns:
            Drawing result.
        """
        pass

    @abstractmethod
    def resize(self, factor: float) -> None:
        """Resize the shape.

        Args:
            factor: Resize factor.
        """
        pass

__init__(renderer)

Initialize shape with a renderer.

Parameters:

Name Type Description Default
renderer Renderer

The renderer implementation to use.

required
Source code in src/design_patterns/structural/bridge.py
def __init__(self, renderer: Renderer) -> None:
    """Initialize shape with a renderer.

    Args:
        renderer: The renderer implementation to use.
    """
    self.renderer = renderer

draw() abstractmethod

Draw the shape.

Returns:

Type Description
str

Drawing result.

Source code in src/design_patterns/structural/bridge.py
@abstractmethod
def draw(self) -> str:
    """Draw the shape.

    Returns:
        Drawing result.
    """
    pass

resize(factor) abstractmethod

Resize the shape.

Parameters:

Name Type Description Default
factor float

Resize factor.

required
Source code in src/design_patterns/structural/bridge.py
@abstractmethod
def resize(self, factor: float) -> None:
    """Resize the shape.

    Args:
        factor: Resize factor.
    """
    pass

Square

Bases: Shape

Concrete square shape.

Source code in src/design_patterns/structural/bridge.py
class Square(Shape):
    """Concrete square shape."""

    def __init__(self, renderer: Renderer, side: float = 5.0) -> None:
        """Initialize square.

        Args:
            renderer: The renderer to use.
            side: Square side length.
        """
        super().__init__(renderer)
        self.side = side

    def draw(self) -> str:
        """Draw square using renderer.

        Returns:
            Drawing result.
        """
        return self.renderer.render_square(self.side)

    def resize(self, factor: float) -> None:
        """Resize square.

        Args:
            factor: Resize factor.
        """
        self.side *= factor

__init__(renderer, side=5.0)

Initialize square.

Parameters:

Name Type Description Default
renderer Renderer

The renderer to use.

required
side float

Square side length.

5.0
Source code in src/design_patterns/structural/bridge.py
def __init__(self, renderer: Renderer, side: float = 5.0) -> None:
    """Initialize square.

    Args:
        renderer: The renderer to use.
        side: Square side length.
    """
    super().__init__(renderer)
    self.side = side

draw()

Draw square using renderer.

Returns:

Type Description
str

Drawing result.

Source code in src/design_patterns/structural/bridge.py
def draw(self) -> str:
    """Draw square using renderer.

    Returns:
        Drawing result.
    """
    return self.renderer.render_square(self.side)

resize(factor)

Resize square.

Parameters:

Name Type Description Default
factor float

Resize factor.

required
Source code in src/design_patterns/structural/bridge.py
def resize(self, factor: float) -> None:
    """Resize square.

    Args:
        factor: Resize factor.
    """
    self.side *= factor

TV

Bases: Device

Concrete TV device.

Source code in src/design_patterns/structural/bridge.py
class TV(Device):
    """Concrete TV device."""

    def __init__(self) -> None:
        """Initialize TV."""
        self._enabled = False
        self._volume = 50

    def is_enabled(self) -> bool:
        """Check if TV is on.

        Returns:
            True if on.
        """
        return self._enabled

    def enable(self) -> None:
        """Turn TV on."""
        self._enabled = True

    def disable(self) -> None:
        """Turn TV off."""
        self._enabled = False

    def get_volume(self) -> int:
        """Get TV volume.

        Returns:
            Volume level.
        """
        return self._volume

    def set_volume(self, percent: int) -> None:
        """Set TV volume.

        Args:
            percent: Volume percentage.
        """
        self._volume = max(0, min(100, percent))

__init__()

Initialize TV.

Source code in src/design_patterns/structural/bridge.py
def __init__(self) -> None:
    """Initialize TV."""
    self._enabled = False
    self._volume = 50

disable()

Turn TV off.

Source code in src/design_patterns/structural/bridge.py
def disable(self) -> None:
    """Turn TV off."""
    self._enabled = False

enable()

Turn TV on.

Source code in src/design_patterns/structural/bridge.py
def enable(self) -> None:
    """Turn TV on."""
    self._enabled = True

get_volume()

Get TV volume.

Returns:

Type Description
int

Volume level.

Source code in src/design_patterns/structural/bridge.py
def get_volume(self) -> int:
    """Get TV volume.

    Returns:
        Volume level.
    """
    return self._volume

is_enabled()

Check if TV is on.

Returns:

Type Description
bool

True if on.

Source code in src/design_patterns/structural/bridge.py
def is_enabled(self) -> bool:
    """Check if TV is on.

    Returns:
        True if on.
    """
    return self._enabled

set_volume(percent)

Set TV volume.

Parameters:

Name Type Description Default
percent int

Volume percentage.

required
Source code in src/design_patterns/structural/bridge.py
def set_volume(self, percent: int) -> None:
    """Set TV volume.

    Args:
        percent: Volume percentage.
    """
    self._volume = max(0, min(100, percent))

VectorRenderer

Bases: Renderer

Concrete implementation for vector rendering.

Source code in src/design_patterns/structural/bridge.py
class VectorRenderer(Renderer):
    """Concrete implementation for vector rendering."""

    def render_circle(self, radius: float) -> str:
        """Render circle as vector.

        Args:
            radius: Circle radius.

        Returns:
            Vector rendering result.
        """
        return f"Drawing circle with radius {radius} as vector"

    def render_square(self, side: float) -> str:
        """Render square as vector.

        Args:
            side: Square side length.

        Returns:
            Vector rendering result.
        """
        return f"Drawing square with side {side} as vector"

render_circle(radius)

Render circle as vector.

Parameters:

Name Type Description Default
radius float

Circle radius.

required

Returns:

Type Description
str

Vector rendering result.

Source code in src/design_patterns/structural/bridge.py
def render_circle(self, radius: float) -> str:
    """Render circle as vector.

    Args:
        radius: Circle radius.

    Returns:
        Vector rendering result.
    """
    return f"Drawing circle with radius {radius} as vector"

render_square(side)

Render square as vector.

Parameters:

Name Type Description Default
side float

Square side length.

required

Returns:

Type Description
str

Vector rendering result.

Source code in src/design_patterns/structural/bridge.py
def render_square(self, side: float) -> str:
    """Render square as vector.

    Args:
        side: Square side length.

    Returns:
        Vector rendering result.
    """
    return f"Drawing square with side {side} as vector"