Design Pattern

Adapter Pattern

Clean Java-only production-ready implementation.


What Problem It Solves

You have an existing class with an interface that doesn't match what your client expects. You can't modify the existing class. Adapter wraps it with the interface your client needs.

Adapter Variants

VariantHowWhen
Class AdapterMultiple inheritance (Java: implementing interface while extending adaptee)When adaptee's interface is fixed and you control the adapter class
Object AdapterComposition (adapter holds a reference to adaptee)More flexible, preferred
Two-Way AdapterAdapter works as both target and adapteeUnusual, rarely needed

Where Adapter Appears in LLD Problems

  • Notification Service: Adapter for Twilio, SendGrid, APNS โ€” all implement NotificationChannel
  • External API integration in any problem: wrap legacy or third-party interfaces
  • DB connection: Wrap JDBC, Redis, file-system with a DataStore interface

Implementation

// โ”€โ”€โ”€ EXAMPLE 1 โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
// WHAT WE ARE IMPLEMENTING:
// A generic notification system integrating a legacy third-party SMS API.
//
// WHERE THE PATTERN FITS IN:
// TwilioAdapter is the Adapter. It implements the target client interface
// NotificationChannel and wraps the Adaptee TwilioService.
// โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
// --- Target interface (what the client expects) ---
interface NotificationChannel {
    boolean send(String recipient, String message);
}

// --- Adaptee (incompatible third-party library) ---
class TwilioService {
    public String dispatchSms(String phoneNumber, String text) {
        System.out.println("  [Twilio] Dispatching to " + phoneNumber + ": " + text);
        return "msg_" + System.currentTimeMillis();
    }
}

// --- Adapter ---
class TwilioAdapter implements NotificationChannel {
    private final TwilioService twilioService;

    public TwilioAdapter(TwilioService twilioService) {
        this.twilioService = twilioService;
    }

    public boolean send(String recipient, String message) {
        String msgId = twilioService.dispatchSms(recipient, message);
        return msgId != null;
    }
}

// --- Client ---
class NotificationService {
    private final NotificationChannel channel;

    public NotificationService(NotificationChannel channel) {
        this.channel = channel;
    }

    public void alert(String recipient, String message) {
        if (channel.send(recipient, message)) {
            System.out.println("  Alert sent successfully to " + recipient);
        }
    }
}

public class Main {
    public static void main(String[] args) {
        NotificationChannel adapter = new TwilioAdapter(new TwilioService());
        NotificationService service = new NotificationService(adapter);
        service.alert("+1234567890", "System is down!");
    }
}

๐Ÿ’ฌReview

Help Us Improve

How helpful was this walkthrough?

Click a star to rate. We actively use this feedback to refine and update our system design content.

Placeholder
Optional but highly appreciated!

Discussion

Share your thoughts, ask questions, or help others.

Loading comments...