From grimoire
Decouple an abstraction from its implementation so both can vary independently, avoiding exponential class hierarchies that result from combining them through inheritance. Best for structural design patterns in OOP.
How this skill is triggered — by the user, by Claude, or both
Slash command
/grimoire:apply-bridge-patternThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Decouple an abstraction from its implementation so that both can vary independently.
Decouple an abstraction from its implementation so that both can vary independently.
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
Abstraction dimension: Shape — Circle, Square, Triangle
Implementation dimension: Renderer — SVGRenderer, CanvasRenderer, PDFRenderer
Any combination should work without a dedicated class for each.
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: ...
class Shape(ABC):
def __init__(self, renderer: Renderer):
self._renderer = renderer # the bridge
@abstractmethod
def draw(self) -> None: ...
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}"/>')
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.
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.
npx claudepluginhub jeffreytse/grimoire --plugin grimoireImplements the Bridge pattern to separate abstraction from implementation, enabling independent variation along two dimensions (e.g., shape+renderer, notification+channel).
Generates Bridge pattern for PHP 8.4 projects, creating abstraction, refined abstraction, implementor interface, concrete implementors, and unit tests in Domain/Infrastructure structure. For decoupling with multiple variation dimensions or runtime switching.
Guides extracting interfaces behind abstractions to decouple callers from concrete implementations, improving testability and reducing change impact.