Design Patterns — Adapter Vs Bridge
Design patterns are the quiet superpowers of software engineering — subtle, elegant solutions that help us build systems that are flexible…
Design Patterns — Adapter Vs Bridge
Design patterns are the quiet superpowers of software engineering — subtle, elegant solutions that help us build systems that are flexible, scalable, and easier to maintain.
In this article would like to uncover use cases and differences of 2 structural design patterns Adapter and Bridge.
At first glance, both patterns seem to deal with connecting components and improving flexibility. But their intentions, use cases, and long‑term impact on system design are fundamentally different.
Adapter pattern
Intent: Make an existing class work with a new interface expected by the client.
Usually retrofitted: you already have one interface in use, and you introduce an adapter because something doesn’t match.
Focus is on compatibility.

Adapter Design Pattern
Here is the “Target Interface” expected by the client
interface PaymentProcessor {
void pay(int amount);
}
New payment integration
class StripeSDK {
void makePayment(double amt) { ... }
}
You cannot change:
- PaymentProcessor (Target)
- Client code
- StripeSDK
So you introduce the adapter class,
- implements the client-facing interface (PaymentProcessor)
- And internally wraps the adaptee (the incompatible class — StripeSDK)
class StripeAdapter implements PaymentProcessor {
private StripeSDK sdk = new StripeSDK();
@Override
public void pay(int amount) {
sdk.makePayment((double) amount);
}
}
- PayPal → calls
PaymentProcessordirectly viaPaypalProcessor. - Stripe → goes through
**StripeAdapter→StripeSDK** to match the samePaymentProcessorinterface.
Bridge pattern (GoF definition)
Intent: Decouple an abstraction from its implementation so the two can vary independently.
Designed-in, not just retrofitted
You have two hierarchies:
- Abstraction hierarchy (what clients depend on)
- Implementation hierarchy (pluggable implementations)
Bridge pattern in plain terms: separate “what you do” (abstraction) from “how you do it” (implementation) so you can change either independently.
Example: Notifications (classic Bridge)
You want to send notifications, and you might send them via Email/SMS. Also, you might have different types of notifications: “Alert”, “Marketing”. You don’t want a class explosion like:
EmailAlertNotification, SmsAlertNotification,
EmailMarketingNotification, SmsMarketingNotification, …
Instead you “bridge” them:
Abstraction hierarchy: Notification (Alert/Marketing)
Implementation hierarchy: Sender (Email/Sms)

Bridge Design Pattern
interface Sender {
void send(String recipient, String message);
}
final class EmailSender implements Sender {
@Override
public void send(String recipient, String message) {
System.out.println("EMAIL to " + recipient + ": " + message);
}
}
final class SmsSender implements Sender {
@Override
public void send(String recipient, String message) {
System.out.println("SMS to " + recipient + ": " + message);
}
}
abstract class Notification {
protected final Sender sender;
protected Notification(Sender sender) {
this.sender = sender;
}
public abstract void notify(String recipient, String message);
}
final class AlertNotification extends Notification {
public AlertNotification(Sender sender) {
super(sender);
}
@Override
public void notify(String recipient, String message) {
sender.send(recipient, "[ALERT] " + message);
}
}
final class MarketingNotification extends Notification {
public MarketingNotification(Sender sender) {
super(sender);
}
@Override
public void notify(String recipient, String message) {
sender.send(recipient, "[MARKETING] " + message);
}
}
// Usage:
// Notification n = new AlertNotification(new SmsSender());
// n.notify("12345", "Price dropped!");
the bridge is the reference held inside the abstraction:
Notification (abstraction) contains a Sender (implementation)
That Sender field is the “bridge” between the two hierarchies
So the “bridge” is achieved by composition (protected final Sender sender;), not by a standalone wrapper class.
Conclusion: Design patterns are not just theoretical constructs — they are practical tools that help us craft systems that remain flexible even as requirements evolve. The Adapter and Bridge patterns often appear similar at first glance, but their intentions are fundamentally different.
The Adapter pattern shines when you need to integrate something new without changing existing client code.
On the other hand, the Bridge pattern helps you grow systems without a combinatorial explosion of subclasses.
메타데이터
- post_id
- db6d4cb9bc0e
- slug
- design-patterns-adapter-vs-bridge-db6d4cb9bc0e
- url
- https://medium.com/@goelsonali/design-patterns-adapter-vs-bridge-db6d4cb9bc0e
- canonical_url
- https://medium.com/@goelsonali/design-patterns-adapter-vs-bridge-db6d4cb9bc0e
- author_url
- https://medium.com/@goelsonali
- status
- ok
- fetched_at
- 2026-06-27 10:07:59