How does the Adapter pattern differ from the Bridge pattern? Both put an object between two types — what actually separates them?
answer
- Adapter = retrofit, Bridge = designed up front
- Bridge: M×N → M+N
- You own both bridge interfaces; adaptee's is imposed
- Bridge refines behavior; adapter only translates
- Bridge implementors are often adapters inside
basics
~10 sAdapter is applied after the fact to make two existing, mismatched interfaces work together. Bridge is designed up front so an abstraction and its implementation can vary independently. Same shape, opposite timing and intent.
solid answer
~60 sStructurally both delegate across an interface boundary, which is why they get confused. The distinctions: **Timing/intent** — Adapter is a retrofit: interfaces already exist and clash, and you make them collaborate without changing either. Bridge is planned before either hierarchy hardens, so that an abstraction (e.g. `Window`) and an implementation (e.g. `RenderingBackend`) can evolve on separate axes and be combined at run time. **Cardinality** — an adapter typically has one target and one adaptee, and its interface is dictated by the pre-existing adaptee; a bridge is deliberately two independently extensible hierarchies, turning an M×N class explosion into M+N. **Who owns the interfaces** — with Bridge you design both sides, so the implementor interface is minimal and primitive-flavoured by choice; with Adapter you inherit the adaptee's shape and must live with its awkwardness. **Behavior** — Bridge's abstraction usually adds refined operations composed from the implementor's primitives; an adapter should add nothing but translation. In practice Bridges and Adapters coexist: the implementor side of a Bridge is often filled by adapters over vendor SDKs.
go deeper
Say Adapter fixes a mismatch you discovered later; Bridge is planned so two things can change independently. One example each.
Add who owns the interfaces and the M×N → M+N argument, and note that both delegate so the diagrams look alike.
Discuss intent-over-structure, refined abstractions adding behavior, and how bridge implementors are frequently adapters over vendor SDKs.
Tie it to dependency inversion and hexagonal ports/adapters, judge when a second axis of variation is real versus speculative, and talk about the cost of a lowest-common-denominator implementor interface.
## Why they look alike Draw the UML and both are "a client-facing type holding a reference to another type it delegates to". GoF itself notes the resemblance and separates them by **intent and lifecycle**, not by shape. Patterns are named by *what problem they solve*, not by their class diagram — this pair is the canonical proof. ## Definitions **Adapter** — *Convert the interface of a class into another interface clients expect.* Participants: Target, Client, Adaptee, Adapter. **Bridge** — *Decouple an abstraction from its implementation so the two can vary independently.* Participants: **Abstraction** (the client-facing type, e.g. `Window`), **RefinedAbstraction** (`IconWindow`, `TransientWindow` — subclasses adding higher-level operations), **Implementor** (a narrow primitive interface, e.g. `WindowImpl.devDrawLine`, `devDrawText`), **ConcreteImplementor** (`XWindowImpl`, `WindowsImpl`). ## The five real differences ### 1. Timing — retrofit vs. designed up front Adapter is applied *after* the mismatch exists, usually because a dependency is third-party or legacy. Bridge is applied *before*, as a deliberate structuring decision anticipating two directions of change. "Adapter makes things work after they're designed; Bridge makes them work before they are." (GoF, paraphrased.) ### 2. Who chooses the interfaces With Bridge you author *both* the Abstraction and the Implementor, so you can make the Implementor deliberately minimal — a handful of primitives. With Adapter, the Adaptee's interface is a given; you cannot make it nicer, only wrap it. That's why adapters often contain gnarly conversion code and bridges usually don't. ### 3. Combinatorics Bridge exists to kill an M×N class explosion. Three window kinds × four platforms = 12 subclasses without a bridge; 3 + 4 = 7 types with one. Adapter has no such goal — one adapter per (target, adaptee) mismatch. If your motivation is "two dimensions of variation", it's a Bridge; if it's "this one library speaks the wrong language", it's an Adapter. ### 4. Added behavior A `RefinedAbstraction` legitimately adds operations: `drawRectangle()` built from four `devDrawLine()` calls. An adapter that starts inventing operations has drifted into Decorator/Facade territory or is hiding a missing domain service. ### 5. Direction of dependency inversion Bridge is a designed application of dependency inversion — high-level abstraction depends on an abstract implementor it owns. Adapter is *rescue* dependency inversion — you invent the port late so existing clients stop depending on the vendor. ## Comparison table | | Adapter | Bridge | |---|---|---| | Intent | Make incompatible interfaces collaborate | Let abstraction and implementation vary independently | | Applied | After the fact (retrofit) | Up front (design decision) | | Interfaces owned by | Client side owns Target; adaptee's shape is imposed | You own both sides | | Typical arity | 1 target ↔ 1 adaptee | M abstractions × N implementors → M+N | | Adds operations? | No, translation only | Yes, refined abstractions compose primitives | | Hierarchies vary? | Usually neither | Both, independently | | Common trigger | Third-party SDK, legacy code, framework callback shape | Platform/backend portability, persistence engines, device drivers | ## They coexist A classic layered design: define a Bridge (`Notification` abstraction × `MessageChannel` implementor). Each ConcreteImplementor — `TwilioChannel`, `SesChannel` — is internally an **Adapter** over the vendor SDK. The Bridge gives you the axis of variation; the Adapters make each real vendor fit the axis. This is also exactly what hexagonal architecture calls a *port* (bridge-like, designed) filled by *adapters* (vendor-shaped). ## Distinguishing questions to ask yourself 1. Did I invent the interface I'm delegating to, or did someone else? (Invented → Bridge-ish.) 2. Am I expecting several implementations *and* several client-side variants? (Yes → Bridge.) 3. Would the problem disappear if I could edit the other class? (Yes → Adapter.) 4. Is my wrapper full of unit/field/error conversion? (Yes → Adapter.) ## Neighbours worth ruling out at the same time - **Facade** — invents a *new, simpler* interface over a whole subsystem; Adapter conforms to an interface that already exists, usually over one object. - **Decorator** — keeps the same interface and adds behavior, recursively. - **Proxy** — keeps the same interface and controls access (lazy, remote, protection). - **Strategy** — same shape as Bridge but the varying part is an *algorithm* chosen per call/context, not an implementation platform.
- Can the same class be both an Adapter and a Bridge implementor?Yes, and it's common. If you design a port (Bridge implementor interface) and each concrete implementor wraps a vendor SDK, that implementor is an Adapter by intent and a Bridge participant by role. Intent is per-relationship, not per-class.
- How does Bridge differ from Strategy, given both delegate to an interface?Strategy varies an *algorithm* — often selected per request and swapped freely at run time, with the client aware a choice exists. Bridge varies the *implementation platform* behind a stable abstraction, usually chosen once at construction, and adds a client-facing abstraction hierarchy of its own. The class diagrams overlap; the intent and the presence of a refined-abstraction hierarchy separate them.
- If an adapter's target interface was designed by you before the vendor was picked, is it still an adapter?The wrapper is still an Adapter (it translates the vendor's shape to yours), but the arrangement is bridge-like: you designed the port for independent variation. This is the hexagonal ports-and-adapters case, and it's a strength, not a contradiction — designing the target up front is what makes vendor swaps cheap.
Adapter is the travel plug you buy at the airport because the hotel socket doesn't fit — an afterthought forced by reality. Bridge is designing the appliance with a detachable power cord in the first place, so any country's cord can be plugged into the same appliance body: two catalogs (appliances, cords) instead of one catalog of every appliance-country combination.
saying these in an interview costs you the question
- Distinguishing them by UML shape rather than intent and timing — the diagrams are nearly identical.
- Saying Bridge is 'just an adapter for two hierarchies' — Bridge's abstraction adds refined operations and both hierarchies extend independently.
- Claiming Adapter can't be planned in advance — a hexagonal port is designed ahead, yet the wrapper is still an adapter.
- Using Bridge as the answer to every 'we might swap the database' question without any second axis of variation — that's speculative generality; a single port + adapters is enough.
- Confusing Adapter with Facade: Facade invents a new simplified interface over a subsystem, Adapter conforms to an existing one.