Home/Learn/Low Level Design/Bridge Pattern

Bridge Pattern

Advanced
Structural Patterns

Decouples an abstraction from its implementation so that the two can vary independently.

Overview

The Bridge pattern avoids a Cartesian product class explosion when you have two independent dimensions of variation. Without Bridge: Shape (Circle, Square) × Rendering (Vector, Raster) = 4 classes. With Bridge: Shape holds a reference to Renderer — 2 + 2 = 4 classes instead of 4, but adding a new Shape costs 1 class (not N renderer variants), and adding a new Renderer costs 1 class (not M shape variants). The abstraction (Shape) delegates rendering work to the implementor (Renderer). This is composition over inheritance applied to two axes of variation.

Shape + Renderer Bridge

Renderer is the Implementor interface. VectorRenderer and RasterRenderer are ConcreteImplementors. Shape is the Abstraction holding a Renderer. Circle and Square are RefinedAbstractions.

Java — Bridge (Shape × Renderer)
// Implementor interface
public interface Renderer {
    void renderCircle(double radius);
    void renderSquare(double side);
}

// Concrete Implementors
public class VectorRenderer implements Renderer {
    @Override
    public void renderCircle(double radius) {
        System.out.printf("Drawing VECTOR circle with radius %.1f%n", radius);
    }
    @Override
    public void renderSquare(double side) {
        System.out.printf("Drawing VECTOR square with side %.1f%n", side);
    }
}

public class RasterRenderer implements Renderer {
    @Override
    public void renderCircle(double radius) {
        System.out.printf("Drawing RASTER circle (pixels) radius %.1f%n", radius);
    }
    @Override
    public void renderSquare(double side) {
        System.out.printf("Drawing RASTER square (pixels) side %.1f%n", side);
    }
}

// Abstraction — holds reference to Implementor (the bridge)
public abstract class Shape {
    protected final Renderer renderer;  // bridge to implementation

    protected Shape(Renderer renderer) {
        this.renderer = renderer;
    }

    public abstract void draw();
    public abstract void resize(double factor);
}

// Refined Abstractions
public class Circle extends Shape {
    private double radius;

    public Circle(Renderer renderer, double radius) {
        super(renderer);
        this.radius = radius;
    }

    @Override public void draw()                  { renderer.renderCircle(radius); }
    @Override public void resize(double factor)   { radius *= factor; }
}

public class Square extends Shape {
    private double side;

    public Square(Renderer renderer, double side) {
        super(renderer);
        this.side = side;
    }

    @Override public void draw()                  { renderer.renderSquare(side); }
    @Override public void resize(double factor)   { side *= factor; }
}

// Combining dimensions independently
Shape vectorCircle = new Circle(new VectorRenderer(), 5.0);
Shape rasterSquare = new Square(new RasterRenderer(), 3.0);

vectorCircle.draw();   // Drawing VECTOR circle with radius 5.0
rasterSquare.draw();   // Drawing RASTER square (pixels) side 3.0

// Switch renderer at runtime
Shape adaptedCircle = new Circle(new RasterRenderer(), 5.0);
adaptedCircle.draw();  // Drawing RASTER circle (pixels) radius 5.0

Bridge vs Strategy

Bridge and Strategy look structurally identical (both use composition with an interface). Intent differs: Bridge separates an abstraction hierarchy from an implementation hierarchy (design-time decision); Strategy swaps algorithms in a single class at runtime (behavioral decision). Bridge is for two varying dimensions; Strategy is for one varying algorithm.

Java — Bridge vs Strategy intent comparison
// Strategy — one class, swappable algorithm (behavioral)
public class Sorter {
    private SortStrategy strategy;                  // swapped at runtime
    public void setStrategy(SortStrategy s) { this.strategy = s; }
    public void sort(int[] arr)             { strategy.sort(arr); }
}

// Bridge — two independent hierarchies (structural)
// Abstraction hierarchy: Report → SalesReport, InventoryReport
// Implementation hierarchy: ReportRenderer → PdfRenderer, ExcelRenderer
public abstract class Report {
    protected final ReportRenderer renderer;        // bridge — set at construction
    protected Report(ReportRenderer renderer)       { this.renderer = renderer; }
    public abstract void generate();
}
// Adding a new Report type: just subclass Report (1 class)
// Adding a new Renderer type: just implement ReportRenderer (1 class)
// No matrix explosion

Key Points to Remember

  • 1Bridge prevents M×N class explosion when two independent dimensions vary.
  • 2The abstraction holds a reference to the implementor — both sides can vary independently.
  • 3Bridge differs from Strategy: Bridge is structural (design-time hierarchy split); Strategy is behavioral (runtime algorithm swap).
  • 4Use Bridge when both the abstraction AND implementation need subclassing independently.
  • 5JDBC is a Bridge: Java application (abstraction) calls DriverManager/Connection API; JDBC driver (implementor) implements for each DB vendor.

Interview Questions

Sign in to ask Aria
1

What problem does Bridge solve that inheritance cannot?

MediumAmazon
2

What is the difference between Bridge and Strategy patterns?

HardGoogle
3

Is JDBC an example of Bridge pattern? Explain.

MediumMicrosoft
4

When would you prefer Bridge over Decorator?

HardAdobe

Ask Aria about Bridge Pattern

Your personal AI tutor — ask anything about this concept

Revision Status

Personal Notes

Sign in to save personal notes for this topic.

Discussion

Sign in to join the discussion.

Loading discussion…