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.
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 { // Abstractionprotected: Renderer& rnd_; // the BRIDGE: HAS-A implementorpublic: 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
- 01Intent — stop the class explosion of two axes
- 02Structure — Abstraction holds an Implementor
- 03Vary the two sides independently
- 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.