Full Stack • Java • System Design • Cloud • AI Engineering

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.