design patterns · advanced

Bridge Pattern

Bridge is a structural GoF pattern that decouples an abstraction from its implementation so the two can vary independently. It solves a combinatorial class explosion: when a Shape (Circle, Square…) must work with each Renderer (OpenGL, SVG, Vulkan…), single inheritance forces M×N classes (GLCircle, SVGCircle, …). Bridge instead defines two independent hierarchies linked by composition. The Implementor (Renderer) declares low-level primitive operations (drawCircle) implemented by concrete implementors; the Abstraction (Shape) holds a reference to an Implementor and defines higher-level operations in terms of those primitives, with refined abstractions (Circle) extending it. Crucially the abstraction does not inherit from the implementor — it delegates across the 'bridge' — and the implementor is injected (usually at construction) so any abstraction pairs with any implementation and can even be swapped at runtime, turning M×N into M+N. Benefits: the two dimensions evolve independently, no subclass blowup, and implementation details stay hidden and switchable. Costs: extra indirection and upfront structure, overkill with only one implementation. It differs from Adapter (which retrofits an existing class to an expected interface after the fact) and Strategy (which swaps a single interchangeable algorithm behind one abstraction); Bridge is planned in advance to separate two orthogonal hierarchies — shapes×renderers, drivers×databases, UI controls×platforms.

🔑 Key line

Bridge (structural): decouple an ABSTRACTION (Shape) from its IMPLEMENTATION (Renderer) into two separate hierarchies joined by composition — the abstraction HOLDS an implementor and delegates to it — so the two axes vary independently and M×N subclasses become M+N. Inject/swap the implementor at runtime. Bridge is planned up front to split two hierarchies, unlike Adapter (retrofit a class) and Strategy (swap one algorithm).

The code

// Bridge — split an ABSTRACTION from its IMPLEMENTATION so the two
// vary independently. Composition (a 'bridge'), not inheritance.
struct Renderer { // Implementor
virtual void drawCircle(float x, float y, float r) = 0;
virtual ~Renderer() = default;
};
struct GLRenderer : Renderer {
void drawCircle(float, float, float) override;
};
struct SVGRenderer : Renderer {
void drawCircle(float, float, float) override;
};
class Shape { // Abstraction
protected:
Renderer& rnd_; // the BRIDGE: HAS-A implementor
public:
explicit Shape(Renderer& r) : rnd_(r) {}
virtual void draw() = 0;
virtual ~Shape() = default;
};
class Circle : public Shape { // Refined Abstraction
float x_, y_, r_;
public:
Circle(Renderer& r, float x, float y, float rad) : Shape(r), x_(x), y_(y), r_(rad) {}
void draw() override {
rnd_.drawCircle(x_, y_, r_);
} // delegate
};
// Mix freely at runtime: any Shape x any Renderer.
GLRenderer gl;
Circle c(gl, 0, 0, 5);
c.draw();

What this lesson walks through

  1. 01Intent — stop the class explosion of two axes
  2. 02Structure — Abstraction holds an Implementor
  3. 03Vary the two sides independently
  4. 04Gotcha — Bridge vs Adapter

When a thing varies along TWO independent axes — Shape {Circle, Square} × Renderer {OpenGL, SVG} — subclassing both gives you n×m classes (CircleGL, CircleSVG, SquareGL…). Bridge splits the axes so you write n+m instead.

See it animated — step by step, at your own pace

Unlock the full interactive walkthrough of Bridge Pattern and 100+ animated C++ interview lessons.

← Previous
Composite Pattern
Next →
Flyweight Pattern