About Us Contact Us Write for Us Advertise
Home > System Design > Low-Level Design > Adapter Pattern in Java (with Example)
System Design › Low-Level Design

Adapter Pattern in Java (with Example)

The Adapter pattern explained: wrap a class with an incompatible interface so it works with the interface your code expects — like a travel plug adapter. Integrating third-party/legacy code, with Java code and UML.

Shiv Pandey
Shiv Pandey
Oct 19, 2026 | 27 views
Adapter Pattern in Java (with Example)

🟢 Design Patterns · Structural · Fresher → 🟠 senior

The Adapter pattern is the software version of a travel plug adapter: your laptop's plug doesn't fit the wall socket in another country, so you slot in an adapter that bridges the two. In code, when you have a class with one interface but your code expects a different interface, an Adapter sits between them and translates. It's how you make incompatible pieces work together without changing either.

In one line: Adapter wraps an object with an incompatible interface and exposes the interface your code expects, translating calls between the two — letting classes that couldn't otherwise cooperate work together.

The problem

Your app talks to payment providers through a PaymentProcessor interface with a pay(amount) method. You integrate a third-party library, but its class has a different method — makePayment(cents, currency). You can't change the library, and you don't want to rewrite your app around its odd interface. The shapes just don't fit.

The solution

🟠 Write an adapter that implements your interface and internally calls the third-party class, translating as needed:

interface PaymentProcessor { void pay(double amount); }   // what your app expects

class StripeLibrary {                                     // the incompatible class
    void makePayment(long cents, String currency) { /*…*/ }
}

class StripeAdapter implements PaymentProcessor {         // the adapter
    private final StripeLibrary stripe = new StripeLibrary();
    public void pay(double amount) {
        stripe.makePayment(Math.round(amount * 100), "USD");  // translate!
    }
}
// client uses YOUR interface, unaware of Stripe's shape:
PaymentProcessor p = new StripeAdapter();
p.pay(19.99);
Clientwants pay() StripeAdaptertranslates StripeLibrarymakePayment() pay() makePayment()

Your app keeps calling pay(); the adapter quietly converts dollars to cents and calls Stripe's method. Neither your code nor the library changed — the adapter absorbed the mismatch.

Where you meet it

🟠 Adapter is everywhere in real systems: wrapping third-party libraries behind your own interface (so you can swap the library later without touching the rest of your code), integrating legacy code with a modern API, and bridging data formats. Java's Arrays.asList() adapts an array to a List; I/O InputStreamReader adapts a byte stream to a character stream. Recognising these as adapters is a nice senior touch.

A hidden benefit: decoupling

🟠 Adapter doesn't just fix a mismatch — it isolates your codebase from an external dependency. Because all your code talks to your PaymentProcessor interface, swapping Stripe for PayPal later means writing one new adapter, not editing the whole app. That's the Dependency Inversion benefit — depend on your abstraction, adapt the outside world to it.

When to use it

Use Adapter when you need to make an existing class work with an incompatible interface — especially with third-party or legacy code you can't modify. If you control both sides, it's usually cleaner to just make the interfaces match; Adapter shines precisely when you can't change one side.

The interview-ready summary

"Adapter wraps a class with an incompatible interface and exposes the one my code expects, translating between them — like a travel plug adapter. I implement my own target interface in an adapter class that delegates to the foreign object, converting arguments as needed. It's how I integrate third-party libraries or legacy code without changing either side, and it decouples my app from the external dependency so I can swap it later by writing a new adapter. Examples include Arrays.asList and InputStreamReader." Clear, with the decoupling insight."

What to read next

← Prototype pattern · Decorator pattern →

Related Articles

Chain of Responsibility Pattern in Java (Example)
System Design › Low-Level Design

Chain of Responsibility Pattern in Java (Example)

Template Method Pattern in Java (with Example)
System Design › Low-Level Design

Template Method Pattern in Java (with Example)

Command Pattern in Java (with Undo Example)
System Design › Low-Level Design

Command Pattern in Java (with Undo Example)

State Pattern in Java (with Example)
System Design › Low-Level Design

State Pattern in Java (with Example)