📘 Why This Blog?
I once tried plugging a new payment system into my existing wallet app.
Sounds simple, right?
Except the new payment API looked nothing like the one I already had.
I ended up rewriting half my code just to make it fit. 🤯
That’s when the Adapter Pattern walked in—like a translator between two worlds.
This blog is my no-fluff, real-world breakdown of the Adapter Pattern—the way I wish someone had explained it when I was pulling my hair out.
📖 What is the Adapter Pattern?
The Adapter Pattern lets you make incompatible interfaces work together.
In simple terms: You wrap one class inside another to make it “look like” what your code expects.
Like an electric plug adapter—it doesn’t change the electricity, just the shape of the socket.
🔍 Spotting an Adapter
You're probably in Adapter territory if:
- You’re integrating with an external API or legacy system
- You find yourself writing conversion code over and over
- Your new class just won’t “fit” the interface your system expects
🧪 Code Example – Payment Gateway Adapter
Step 1: The Expected Interface
public interface IPaymentProcessor {
void pay(int amount);
}
Step 2: An Existing Payment Gateway (Incompatible)
public class FancyPaySDK {
public void makeTransaction(double valueInDollars) {
System.out.println("Transaction of $" + valueInDollars + " done via FancyPay");
}
}
Step 3: The Adapter
public class FancyPayAdapter implements IPaymentProcessor {
private final FancyPaySDK fancyPay;
public FancyPayAdapter(FancyPaySDK fancyPay) {
this.fancyPay = fancyPay;
}
@Override
public void pay(int amount) {
// Assume 1 unit = 1 dollar for simplicity
fancyPay.makeTransaction(amount);
}
}
Step 4: Client Code
public class Checkout {
private final IPaymentProcessor processor;
public Checkout(IPaymentProcessor processor) {
this.processor = processor;
}
public void completeOrder(int amount) {
processor.pay(amount);
}
}
public class Main {
public static void main(String[] args) {
FancyPaySDK fancyPay = new FancyPaySDK();
IPaymentProcessor adapter = new FancyPayAdapter(fancyPay);
Checkout checkout = new Checkout(adapter);
checkout.completeOrder(100); // $100 via FancyPay
}
}
⚠ Important Notes
- You’re not changing
FancyPaySDK
- You're wrapping it in an Adapter to fit the
IPaymentProcessor
interface - This keeps your client code clean and decoupled
🤔 When to Use Adapter
- Integrating with legacy systems or third-party libraries
- Making two interfaces compatible without modifying either
- Bridging between new and old code in large systems
✅ Benefits
- Helps reuse existing code without modifying it
- Promotes interface-driven design
- Makes integration painless and clean
❗ Caution
- Too many adapters can lead to complexity and confusion
- If you're writing lots of tiny adapters, rethink your abstractions
- Avoid adapting things that should be redesigned instead
🔗 More Examples
🥵 TL;DR
The Adapter Pattern is like a plug converter.
Instead of:
“I’ll rewrite my system to match this new class…”
You say:
“I’ll wrap it so it fits my system.”
Adapt. Don’t force. Write clean bridges between old and new.
Be the Integrator, not the Imitator. ⚙️
Made with ❤️ by syedyshiraZ
Top comments (0)