Structural · DWG NO. 011

Bridge

Split an abstraction from its implementation so each can change independently, instead of multiplying subclasses.

TypeStructural
ScopeTwo hierarchies
ComplexityMedium
Common inCross-platform rendering, device drivers, remote controls

Two dimensions of variation, multiplied together

A `Shape` that can be `Circle` or `Square`, rendered by either `RasterRenderer` or `VectorRenderer`, tempts you into `RasterCircle`, `VectorCircle`, `RasterSquare`, `VectorSquare`. Add a third shape or renderer and the subclass count multiplies again.

Compose instead of multiplying subclasses

The abstraction (Shape) holds a reference to an implementation (Renderer) rather than inheriting from it. Either hierarchy can grow — new shapes or new renderers — without touching the other.

CircleSquarehas-aRenderer(interface)RasterVector

Shapes rendered independently of the renderer used

Any shape can be paired with any renderer at construction time — the pairing is a runtime choice, not a class.

shape-bridge.js
const RasterRenderer = { render: (desc) => console.log(`[raster] drawing ${desc}`) };
const VectorRenderer = { render: (desc) => console.log(`[vector] drawing ${desc}`) };

class Shape {
  constructor(renderer) { this.renderer = renderer; }
}

class Circle extends Shape {
  draw() { this.renderer.render("circle"); }
}

class Square extends Shape {
  draw() { this.renderer.render("square"); }
}

new Circle(RasterRenderer).draw(); // [raster] drawing circle
new Circle(VectorRenderer).draw(); // [vector] drawing circle
new Square(VectorRenderer).draw(); // [vector] drawing square

Trade-offs