AcademyDesign Patterns
Bridge pattern
Letting two dimensions of variation grow independently instead of multiplying into N times M classes, the two hierarchies it costs, and the if/else sneaking that growth back.
6 min readUpdated 3 exercises
Bridge solves a problem the wrap-and-forward patterns don't touch: two independent ways an object can vary that would otherwise multiply against each other instead of simply adding.
Without Bridge, "shape" times "color" needs one subclass per combination: a class for a red circle, another for a blue circle, another for a red square, and every new color multiplies every existing shape. Bridge splits the two dimensions into separate hierarchies and connects them through composition instead of inheritance. A shape holds a reference to a color instead of extending one, so N shapes and M colors need N + M classes, never N × M.
The problem it solves
Your app sends notifications. There are different kinds (an alert, a reminder) and different channels (email, SMS, push). If each combination is its own subclass, you write AlertEmail, AlertSms, AlertPush, ReminderEmail, ReminderSms, ReminderPush.
- Six classes for two kinds and three channels. Add a fourth channel and you write two more. Add a third kind and you write four more.
- Duplicated code. The email logic is copied into every kind that supports email.
- Rigid at runtime. A notification cannot change channel after it is created, because the channel is baked into its class.
The two dimensions have nothing to do with each other. They should not be tied into one hierarchy.
Structure
Four parts:
- The abstraction (
Circle,Square): the high-level side, which holds a reference to the implementation. - The implementation interface (
Color): the low-level operations the abstraction relies on. - Concrete implementations (
Red,Blue). - Refined abstractions: extra kinds of abstraction, each free to work with any implementation.
class Red {
fill() { return 'red'; }
}
class Blue {
fill() { return 'blue'; }
}
class Circle {
constructor(color) { this.color = color; }
draw() { return 'circle filled ' + this.color.fill(); }
}
class Square {
constructor(color) { this.color = color; }
draw() { return 'square filled ' + this.color.fill(); }
}
// new Circle(new Red()).draw() → 'circle filled red'
// new Square(new Blue()).draw() → 'square filled blue'Add a third color and nothing about Circle or Square changes. Only a new Color implementation appears. That is the payoff Bridge is named for: the reference a shape holds to a color is the bridge, and it lets the two hierarchies grow independently instead of multiplying each other.
Where it is used in real systems
| Use case | The two dimensions |
|---|---|
| Notifications | Kind (alert, reminder) and channel (email, SMS, push). |
| Cross-platform UI | Widget type (button, dialog) and platform renderer (web, desktop). |
| Logging | Logger type (audit, error) and output (console, file, remote service). |
| Payments | Payment flow (one-off, subscription) and provider (Stripe, PayPal). |
| Remote controls | Remote type (basic, advanced) and device (TV, radio). |
| Database access | Repository type (users, orders) and the storage engine behind it. |
| Reports | Report type (sales, usage) and export format (PDF, CSV). |
Whenever you catch yourself naming a class with two adjectives, such as PdfSalesReport, ask whether two things are varying independently.
Bridges you already use
- Logging libraries. A logger (the abstraction) writes through transports (the implementation): console, file, a hosted service. You pick each independently, and pino or Winston work this way.
- Graphics and UI toolkits. A drawing API that renders to canvas, SVG or a PDF through interchangeable backends.
- JDBC and database drivers. One query API, many interchangeable drivers underneath.
- Dependency injection. Passing a
Senderinto a notification's constructor is Bridge, whether or not it was called that.
Bridge or Strategy
The code looks nearly the same, which is why interviewers ask.
- Strategy is about swapping one algorithm inside one class. One dimension.
- Bridge is a structural decision made up front: two hierarchies that evolve separately, designed to avoid a class explosion. Two dimensions.
If you are choosing how one thing is done, it is Strategy. If you are preventing a grid of subclasses, it is Bridge.
When not to use it
- Only one dimension varies. With just one hierarchy, Bridge adds an interface and a reference for nothing.
- The combinations are few and fixed. Two shapes and two colors that will never grow are simpler as four classes.
- The split is artificial. If the "implementation" is always chosen by the abstraction, they are one thing and the interface hides nothing.
- Design-time only. It needs foresight. Retrofitting it into a large existing hierarchy is a real refactor.
What interviewers ask
- "What is the Bridge pattern?" Separating an abstraction from its implementation so both can vary independently.
- "What problem does it solve?" The class explosion from combining two dimensions through inheritance.
- "Bridge versus Adapter?" Adapter fixes an incompatibility after the fact. Bridge is designed up front so the parts stay independent.
- "Bridge versus Strategy?" Strategy swaps an algorithm. Bridge separates two hierarchies.
- "Give an example." Notifications by kind and channel, or a logger and its transports.
The mistake to avoid
A Bridge collapsed back into one hierarchy the moment a shape starts branching on its own color with an if/else. If Circle.draw() contains if (color === 'red'), the abstraction knows about the implementation and the bridge is gone. Every decision about color belongs behind the Color interface.
The mechanism above, an object holding a reference to another and delegating to it, is the same in JavaScript, Python or Java. Only the syntax changes.
Now practice it
1 challenge · 2 quizzesReading this page is the cheap half. These are the exercises that make you use it.
- BridgeProSplit two dimensions of variation into separate hierarchies and prove N + M classes replace N × M — the growth this page's diagram is built to avoid.ChallengeSolve · MediumChallengeSolve · Medium
- Design Patterns · Structural PatternsTen quick questions across Adapter, Decorator, Facade, Proxy, Bridge, Composite and Flyweight, to check the mental model before this one.QuizTake · MediumQuizTake · Medium
- Design Patterns · Structural Patterns — Series 2ProA second, tougher pass on the same structural family, for once the first set feels easy.QuizTake · MediumQuizTake · Medium
Read next
Composite pattern
Treating a single object and a group of them through one interface, the cost every leaf pays for methods it may never use, and a leaf that accepts children it cannot hold.
6 min
Flyweight pattern
Sharing the identical, expensive part of many objects instead of duplicating it, the strict immutability it demands, and one write to shared state corrupting every instance.
6 min