Skip to content
Back to skills

Apply Bridge Pattern

ASecurity

Use when you need to vary both an abstraction and its implementation independently — avoiding an exponential class hierarchy that results from combining them through inheritance.

  • 4 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added September 8, 2026
ai-agentspythongojavadatabasedocumentation

Security analysis

A100/100

Scanned September 8, 2026

npx -y skills add jeffreytse/grimoire-core --skill apply-bridge-pattern --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Apply Bridge Pattern?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Apply Bridge Pattern
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/jeffreytse-apply-bridge-pattern/badge)](https://www.skillsdirectory.com/skills/jeffreytse-apply-bridge-pattern)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: apply-bridge-pattern
description: "Use when you need to vary both an abstraction and its implementation independently — avoiding an exponential class hierarchy that results from combining them through inheritance."
source: "Gamma, Helm, Johnson, Vlissides, \"Design Patterns: Elements of Reusable Object-Oriented Software\" (1994) pp. 151–161; Java AWT (abstraction: Shape hierarchy; implementation: rendering pipeline); Android View system; JDBC (abstraction: Connection; implementation: vendor driver)"
tags: [design-patterns, structural, bridge, oop, developer, extensibility, abstraction-implementation]
related: [apply-adapter-pattern, apply-composition-over-inheritance, apply-solid-principles]
---

# Apply Bridge Pattern

Decouple an abstraction from its implementation so that both can vary independently.

## Why This Is Best Practice

**Adopted by:** Java AWT rendering pipeline (Shape abstraction + platform renderer
implementation — ships in every JVM), JDBC (Connection abstraction + vendor-specific
driver implementation — every Java database program uses this), Android's View system
(View abstraction + Canvas implementation), and .NET's Graphics class hierarchy.
**Impact:** GoF shows that without Bridge, combining M abstractions × N implementations
requires M×N classes. With Bridge, it requires M+N classes. A real example: a graphics
library with 3 shapes (Circle, Square, Triangle) × 3 renderers (SVG, Canvas, PDF)
needs 9 classes without Bridge, 6 with it — and adding a 4th renderer requires 3 new
classes vs. 1.
**Why best:** The alternative — inheritance — permanently binds abstraction to
implementation. `SVGCircle extends Circle` cannot use a PDF renderer without a new
subclass. Bridge separates the dimensions, making each independently extensible.

Sources: Gamma et al. (1994) pp. 151–161; Java AWT documentation; JDBC specification

## Steps

### Step 1: Identify the two independent variation dimensions

```
Abstraction dimension: Shape — Circle, Square, Triangle
Implementation dimension: Renderer — SVGRenderer, CanvasRenderer, PDFRenderer
```

Any combination should work without a dedicated class for each.

### Step 2: Define the implementation interface

```python
from abc import ABC, abstractmethod

class Renderer(ABC):
    @abstractmethod
    def render_circle(self, x: float, y: float, radius: float) -> None: ...

    @abstractmethod
    def render_rect(self, x: float, y: float, w: float, h: float) -> None: ...
```

### Step 3: Define the abstraction holding a reference to the implementation

```python
class Shape(ABC):
    def __init__(self, renderer: Renderer):
        self._renderer = renderer   # the bridge

    @abstractmethod
    def draw(self) -> None: ...
```

### Step 4: Extend both hierarchies independently

```python
class Circle(Shape):
    def __init__(self, renderer: Renderer, x: float, y: float, radius: float):
        super().__init__(renderer)
        self._x, self._y, self._radius = x, y, radius

    def draw(self) -> None:
        self._renderer.render_circle(self._x, self._y, self._radius)

class SVGRenderer(Renderer):
    def render_circle(self, x, y, radius):
        print(f'<circle cx="{x}" cy="{y}" r="{radius}"/>')

    def render_rect(self, x, y, w, h):
        print(f'<rect x="{x}" y="{y}" width="{w}" height="{h}"/>')
```

### Step 5: Compose at runtime — any abstraction with any implementation

```python
svg = SVGRenderer()
pdf = PDFRenderer()

Circle(svg, 10, 10, 5).draw()   # SVG circle
Circle(pdf, 10, 10, 5).draw()   # PDF circle — same Circle class, different renderer
```

Adding a new renderer requires one new `Renderer` subclass. Adding a new shape
requires one new `Shape` subclass. Neither side affects the other.

## When NOT to Use

- **When only one dimension varies** — if the implementation never changes, composition or a simple strategy suffices. Bridge adds abstraction overhead without payoff.
- **When both hierarchies are shallow (1–2 subclasses each)** — the simplification only pays off at 3+ variants per dimension.

## Common Mistakes

**Confusing Bridge with Adapter.** Adapter makes incompatible interfaces work together after the fact. Bridge separates abstraction from implementation from the start, by design. If you're retrofitting, it's Adapter.

**Putting abstraction logic in the implementation.** The implementation interface should only expose primitives (render_circle, render_rect). If it contains domain logic, the bridge leaks.

**Over-engineering for a single renderer.** If there's only one implementation and no plan to add more, Bridge is premature. Add it when the second implementation dimension appears.

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…