It acts as a bridge between an existing class and the client that expects a different interface.
The pattern is particularly useful when integrating legacy systems, third-party libraries, or external services whose interfaces cannot be changed.
Instead of rewriting existing code, an adapter converts requests from one interface into another that the client understands.
In simple terms, the adapter "translates" one interface into another, allowing otherwise incompatible components to collaborate seamlessly.
Structure
The Adapter Pattern consists of following participants.1. The Client interacts only with the Target interface.
2. The Adaptee is the existing class with an incompatible interface.
3. The Adapter implements the Target interface while internally delegating calls to the Adaptee.

Java Implementation
Suppose an application processes payments through a common interface.A new third-party payment provider is introduced, but it exposes a completely different API. Rather than changing the existing application, an adapter can bridge the two interfaces.
public interface PaymentProcessor {
void processPayment(double amount);
}
The application already depends on this interface.
public class PaypalProcessor implements PaymentProcessor {
@Override
public void processPayment(double amount) {
System.out.println("Processing payment using PayPal: " + amount);
}
}
A third-party payment gateway exposes an incompatible API.
public class StripeGateway {
public void makePayment(double amount) {
System.out.println("Processing payment using Stripe: " + amount);
}
}
The adapter converts the existing interface into the one expected by the application.
public class StripeAdapter implements PaymentProcessor {
private final StripeGateway stripeGateway;
public StripeAdapter(StripeGateway stripeGateway) {
this.stripeGateway = stripeGateway;
}
@Override
public void processPayment(double amount) {
stripeGateway.makePayment(amount);
}
}
The client continues to work with the common interface.
public class Main {
public static void main(String[] args) {
PaymentProcessor paypal = new PaypalProcessor();
paypal.processPayment(1000);
PaymentProcessor stripe = new StripeAdapter(new StripeGateway());
stripe.processPayment(2500);
}
}
Output:
Processing payment using PayPal: 1000.0
Processing payment using Stripe: 2500.0
How It Works?
The client communicates only with the PaymentProcessor interface and has no knowledge of the concrete implementations. When PayPal is used, the request is handled directly by PaypalProcessor.When Stripe is used, the client still invokes processPayment(), but the StripeAdapter translates that request into a call to makePayment() on the third-party StripeGateway.
From the client's perspective, both payment providers expose the same interface even though their underlying implementations are completely different.
This keeps the client code unchanged while allowing new providers to be integrated easily.
Advantages
1. The Adapter Pattern enables existing classes to work together without modifying their source code.2. It promotes reusability by allowing legacy or third-party components to be integrated into new applications.
3. Since the client depends only on the target interface, the application remains loosely coupled and new adapters can be introduced with minimal changes.
Disadvantages
1. Introducing adapters adds additional classes to the codebase, which can increase complexity if used excessively.2. An adapter also introduces an extra level of indirection, although the runtime overhead is usually negligible.
3. If many incompatible interfaces must be supported, maintaining numerous adapters may become cumbersome.
JDK Examples
The Adapter Pattern appears throughout the Java ecosystem.1. The java.io.InputStreamReader adapts a byte-oriented InputStream into a character-oriented Reader, allowing character-based APIs to work with byte streams.
2. The java.util.Arrays.asList() method adapts an array into the List interface, allowing array data to be used with collection-based APIs.
Summary
The Adapter Pattern allows incompatible interfaces to work together by introducing an intermediary class that converts one interface into another.By keeping the client dependent only on the target interface, the Adapter Pattern promotes flexibility, reuse, and maintainability in object-oriented applications.