Adapter Design Pattern in Java
Learn Adapter Design Pattern in Java with real-world examples, legacy system integration, third-party APIs, Spring examples, UML diagrams, code examples, benefits, limitations, and interview questions.
Introduction
In enterprise applications, we frequently integrate with:
- Legacy Systems
- Third-Party APIs
- External Vendors
- Banking Gateways
- Insurance Providers
- Cloud Services
The problem is:
Different systems often expose different interfaces.
Your application expects one interface.
The external system provides another interface.
This mismatch is solved using:
Adapter Design Pattern
Purpose of Adapter Pattern
The main purpose of Adapter Pattern is:
Convert one interface into another interface that the client expects.
Adapter acts as a translator between incompatible systems.
Real World Analogy
Imagine you travel from India to the USA.
Your laptop charger has:
Indian Plug
But the USA wall socket supports:
US Plug
You use:
Power Adapter
The adapter converts one format into another.
Similarly:
Application Interface
↓
Adapter
↓
Third Party Interface
Adapter Pattern Definition
Adapter allows two incompatible interfaces to work together without modifying their source code.
Real Enterprise Example
Suppose your application expects:
PaymentProcessor
But a third-party vendor provides:
StripeGateway
Their methods are different.
Adapter bridges the gap.
Without Adapter
flowchart LR
A[Client]
A --> B[Expected Interface]
B --> C[Incompatible Third Party API]
Communication fails.
With Adapter
flowchart LR
A[Client]
A --> B[Adapter]
B --> C[Third Party API]
Communication succeeds.
Adapter Pattern Structure
classDiagram
class Client
class Target {
<<interface>>
+processPayment()
}
class Adapter {
+processPayment()
}
class Adaptee {
+makePayment()
}
Target <|.. Adapter
Adapter --> Adaptee
Client --> Target
Components
Target
Interface expected by the client.
Adaptee
Existing class with incompatible interface.
Adapter
Converts target calls into adaptee calls.
Client
Uses target interface.
Example Scenario
Your application expects:
processPayment()
Vendor provides:
makePayment()
Need translation.
Step 1: Create Target Interface
public interface PaymentProcessor {
void processPayment(double amount);
}
Step 2: Third-Party Vendor Class
public class StripeGateway {
public void makePayment(double amount) {
System.out.println(
"Stripe Payment Processed: $" + amount);
}
}
Cannot modify vendor code.
Step 3: Create Adapter
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);
}
}
Step 4: Client Code
public class AdapterDemo {
public static void main(String[] args) {
StripeGateway gateway =
new StripeGateway();
PaymentProcessor processor =
new StripeAdapter(gateway);
processor.processPayment(500);
}
}
Output
Stripe Payment Processed: $500.0
Object Flow
sequenceDiagram
participant Client
participant Adapter
participant Stripe
Client->>Adapter: processPayment(500)
Adapter->>Stripe: makePayment(500)
Stripe-->>Adapter: Success
Adapter-->>Client: Success
Banking Example
Suppose a bank integrates with:
Visa Gateway
MasterCard Gateway
Amex Gateway
Each provider exposes different APIs.
Instead of changing business logic:
Create adapters.
Banking Architecture
flowchart TD
A[Payment Service]
A --> B[Visa Adapter]
A --> C[MasterCard Adapter]
A --> D[Amex Adapter]
B --> E[Visa API]
C --> F[MasterCard API]
D --> G[Amex API]
Insurance Example
Insurance platform integrates:
LexisNexis
Experian
TransUnion
Each vendor returns data differently.
Adapters standardize responses.
Legacy System Example
Many banks still use:
Mainframe Systems
COBOL Services
SOAP Services
Modern applications use:
REST APIs
JSON
Spring Boot
Adapter helps bridge old and new systems.
Legacy Integration Diagram
flowchart LR
A[Spring Boot Service]
A --> B[Adapter]
B --> C[SOAP Service]
C --> D[Mainframe]
Notification Example
Application expects:
sendNotification()
Vendor API provides:
sendMessage()
Adapter converts the call.
Example
public interface NotificationService {
void sendNotification(String message);
}
Vendor API
public class TwilioClient {
public void sendMessage(String message) {
System.out.println(
"Twilio Message Sent: " + message);
}
}
Adapter
public class TwilioAdapter
implements NotificationService {
private final TwilioClient client;
public TwilioAdapter(TwilioClient client) {
this.client = client;
}
@Override
public void sendNotification(String message) {
client.sendMessage(message);
}
}
Output
Twilio Message Sent: OTP Generated
Spring Boot Example
Adapter Pattern is very common in enterprise Spring applications.
Service Layer:
public interface PaymentProvider {
void pay(double amount);
}
Stripe Adapter
@Service
public class StripeAdapter
implements PaymentProvider {
private final StripeGateway stripeGateway;
public StripeAdapter() {
this.stripeGateway =
new StripeGateway();
}
@Override
public void pay(double amount) {
stripeGateway.makePayment(amount);
}
}
Controller
@RestController
@RequestMapping("/payments")
public class PaymentController {
private final PaymentProvider provider;
public PaymentController(
PaymentProvider provider) {
this.provider = provider;
}
@PostMapping
public String pay() {
provider.pay(1000);
return "Payment Successful";
}
}
API Input
POST /payments
API Output
Payment Successful
Adapter in Microservices
Very common for:
- REST API Integration
- SOAP Integration
- Kafka Message Conversion
- Database Migration
- Vendor Integration
Kafka Example
Service A produces:
{
"customerId":"100",
"name":"Venu"
}
Service B expects:
{
"id":"100",
"customerName":"Venu"
}
Adapter transforms payload.
Microservice Architecture
flowchart LR
A[Service A]
A --> B[Adapter]
B --> C[Service B]
Java Framework Examples
Adapter Pattern appears in:
| Framework | Example |
|---|---|
| Spring MVC | HandlerAdapter |
| Spring Security | UserDetailsAdapter |
| JDBC | Driver Adapter |
| SLF4J | Logging Adapter |
| Kafka | Message Converter |
| JPA | Entity Adapters |
Spring MVC Example
Spring DispatcherServlet uses:
HandlerAdapter
to invoke different controller types using a common interface.
Benefits
✅ Reuse Existing Code
✅ No Modification Required
✅ Supports Legacy Systems
✅ Easy Third-Party Integration
✅ Follows Open Closed Principle
✅ Reduces Coupling
✅ Improves Maintainability
Limitations
❌ Adds Extra Layer
❌ More Classes
❌ Can Increase Complexity
❌ Too Many Adapters Can Become Hard To Manage
When To Use
Use Adapter when:
- Integrating external systems
- Working with legacy applications
- Third-party APIs have different interfaces
- Migration projects
- Vendor integrations
When Not To Use
Avoid Adapter when:
- Interfaces are already compatible
- Additional abstraction is unnecessary
- Direct implementation is simpler
Adapter vs Facade
| Feature | Adapter | Facade |
|---|---|---|
| Purpose | Convert Interface | Simplify Interface |
| Focus | Compatibility | Usability |
| Used For | Integration | Simplification |
Adapter vs Decorator
| Feature | Adapter | Decorator |
|---|---|---|
| Goal | Change Interface | Add Behavior |
| Client Interface | Different | Same |
| Usage | Integration | Enhancement |
Interview Questions
What is Adapter Pattern?
A structural pattern that converts one interface into another interface expected by the client.
Why is Adapter called a Wrapper?
Because it wraps an existing class and exposes a new interface.
Real World Example?
Power adapter converting Indian plug to US plug.
Where is Adapter used in Enterprise Applications?
- Payment Gateways
- SOAP Integration
- REST Integration
- Kafka Transformation
- Legacy System Migration
Is Adapter used in Spring?
Yes.
Examples:
- HandlerAdapter
- UserDetails Adapter
- Message Converters
Key Takeaways
- Adapter is a Structural Design Pattern.
- It allows incompatible interfaces to work together.
- Commonly used in enterprise integrations.
- Frequently appears in banking and insurance systems.
- Enables migration from legacy systems.
- Widely used in Spring Framework and Microservices.
- One of the most practical design patterns used in real-world projects.