Menu

Earn Premium with Referrals

Invite your friends and earn Premium rewards through our referral program.

See how it works and start inviting friends.

Bridge
LLD

Bridge

Understand how to separate abstraction from implementation so both can evolve independently.

Bridge: Separating Abstraction From Implementation

The Problem It Solves

Remotes and devices both vary. Basic remote, advanced remote; TV, radio. Inheritance across both axes at once forces the cross-product: BasicTvRemote, AdvancedTvRemote, BasicRadioRemote, AdvancedRadioRemote — 2×2 = 4 classes, 3×3 = 9, m×n grows multiplicatively, every new device re-touches every remote class. Bridge splits the axes and joins them with composition: abstractions hold a reference to an implementor interface; each axis extends independently.

 INHERITANCE ACROSS TWO AXES            BRIDGED

 Remote                                 Remote ───── holds ────► Device ◁ interface
 ├── TvRemote                                                    ├── Tv
 │    └── AdvancedTvRemote                                       └── Radio
 └── RadioRemote                     Abstraction side (m classes) ×
      └── AdvancedRadioRemote        Implementor side (n classes) = m + n total,
 4 classes now; 3×3 = 9 later       new axis entries never touch the other side

Mechanics

// IMPLEMENTOR AXIS — how operations reach a device:
interface Device {
    void setVolume(int pct);
    int volume();
}

class Tv implements Device { /* real impl */ }
class Radio implements Device { /* real impl */ }

// ABSTRACTION AXIS — what users can do:
abstract class Remote {
    protected final Device device;                 // THE bridge reference

    Remote(Device d) { this.device = d; }
    void volumeUp() { device.setVolume(device.volume() + 10); }
}

class AdvancedRemote extends Remote {              // extends ONLY its own axis
    AdvancedRemote(Device d) { super(d); }
    void mute() { device.setVolume(0); }
}

// any pairing works — assembled at runtime:
new AdvancedRemote(new Tv());
new BasicRemote(new Radio());

Remote subclasses never subclass devices; they call them through the Device contract. The two hierarchies vary independently forever.

Recognizing Bridge-Worthy Designs

The signal is two independent “how it varies” questions:

Abstraction axisImplementor axis
Message types (alert/report)Senders (email/SMS/push)
ShapesRenderers (screen/vector/printer)
Payment flowsGateways

If you draw a hierarchy and realize every level multiplies by another dimension, that is the refactor point.

Mechanics of Migration (from inheritance tangle to bridge)

  1. Extract the lower axis into an interface (Device).
  2. Replace parent-class fields in concrete combos with that interface.
  3. Delete cross-product classes; wire pairings in composition root.
  4. Class count drops from m×n to m+n — the arithmetic payoff worth stating in interviews.

vs Strategy vs Adapter

PatternDistinction
BridgeStructural split of two stable axes, decided at construction
StrategyBehavior swapped per operation/lifecycle; single axis
AdapterMakes an existing incompatible thing fit; no two-axis design intent

Bridge is often described as strategy applied structurally at design time — close enough for interviews if the axis-independence point lands.

Trade-offs & Pitfalls

  • Gains: linear growth on both axes; runtime pairing; each side compiles independently.
  • Costs: extra indirection layer; pointless when one axis is frozen (a second dimension that never varies needs no bridge — YAGNI).
  • Over-application warning: single-varying-axis designs dressed as bridges add ceremony without removing explosion risk.

Interview Framing

  • The m×n → m+n arithmetic plus one concrete axis-pair example (“message × sender”) is the complete expected answer.

My Private Notes

Notes are auto-saved locally to this device.