Design pattern "Adapter"

Let's learn what is the Adapter design pattern
Monday, February 12, 2024

Real world example

A real-world application of the adapter pattern in this scenario could be seen in a multilingual conference or business meeting where participants speak different languages and require interpretation services to communicate effectively.

Let’s consider three individuals: Alice, who speaks English, Pierre, who speaks French, and Maria, an interpreter fluent in both languages. Here’s how the adapter pattern can be applied:

  1. Define the Common Interface: In this case, the common interface would represent the communication method between participants, which is the ability to speak and understand each other.

  2. Create Adapters for Different Languages:

    • Alice and Pierre represent the participants who speak different languages and cannot directly communicate with each other.
    • Maria acts as an interpreter, who can adapt messages between Alice and Pierre.
  3. Utilize the Adapters:

    • Alice speaks English, but Pierre speaks French. They cannot understand each other directly.
    • Maria, the interpreter, acts as an adapter. She listens to what Alice says in English, interprets it into French for Pierre, and vice versa.

Here’s how the scenario would play out:

Alice (English Speaker) --> Maria (Interpreter) --> Pierre (French Speaker)
Pierre (French Speaker) --> Maria (Interpreter) --> Alice (English Speaker)

In this scenario:

  • Maria’s role as an interpreter represents the adapter. She adapts the messages between Alice and Pierre, allowing them to communicate effectively despite speaking different languages.
  • Alice and Pierre communicate indirectly through Maria, who serves as a bridge between them.
  • This adaptation process ensures seamless communication between individuals who speak different languages, demonstrating the adapter pattern’s real-world applicability in facilitating interoperability between incompatible interfaces or systems.

In plain words

Adapter pattern lets you wrap an otherwise incompatible object in an adapter to make it compatible with another class.

Wikipedia definition

In software engineering, the adapter pattern is a software design pattern that allows the interface of an existing class to be used as another interface. It is often used to make existing classes work with others without modifying their source code.

Programmatic example

Consider a notification service application.

First we have an interface Notification that all types of providers have to implement

interface Notification {
void send();
}
class EmailNotification implements Notification {
public void send() { }
}
class PushNotification implements Notification {
public void send() { }
}

And the application expects any implementation of Notification interface to work.

class Application {
public void sendNotification(Notification notification) {
notification.send();
}
}

Now let’s say we have to add a SMSNotification in our application (from an another package), and we CANNOT modify it.

We can’t implement it directly because SMSNotification has a different interface. To make it compatible, we will have to create an adapter that is compatible.

class SMSNotification {
public void sendSMS() { }
}
// Adapter around SMSNotification to make it compatible with the application
class SMSNotificationAdapter implements Notification {
protected SMSNotification smsNotification;
public SMSNotificationAdapter(SMSNotification smsNotification) {
this.smsNotification = smsNotification;
}
public void send() {
smsNotification.sendSMS();
}
}

And now the SMSNotification can be used in our application using SMSNotificationAdapter.

public class Main {
public static void main(String[] args) {
EmailNotification emailNotification = new EmailNotification();
SMSNotificationAdapter smsNotification = new SMSNotificationAdapter(new SMSNotification());
Application application = new Application();
application.sendNotification(emailNotification);
application.sendNotification(smsNotification); // Works too !
}
}

Diagram

Loading graph...

In this example, we CANNOT modify the SMSNotification class. Therefore, we need to create an intermediary class that acts as a connector between our implementation and the SMSNotification implementation.

Some other examples

  1. Currency Conversion System: Implement an interface for different currency converters. Create adapters for specific currency conversion APIs to make them compatible.

  2. Language Translation Tool: Define an interface for language translation services. Develop adapters for different translation APIs to enable integration.

  3. File Format Conversion Tool: Create an interface for file format converters. Implement adapters for converting files between various formats (e.g., PDF to Word).

  4. Authentication System: Design a unified authentication interface. Develop adapters for different authentication providers (e.g., Google, Facebook, LDAP).

  5. Payment Gateway Integration: Create an interface for processing payments. Develop adapters for different payment gateways (e.g., PayPal, Stripe, Square).

  6. Camera Interface for Smartphones: Design a common interface for accessing smartphone cameras. Develop adapters for different camera APIs to ensure compatibility.

  7. Remote Control for Smart Devices: Define a common interface for remote control functions. Implement adapters for various smart devices (e.g., smart TVs, air conditioners).

  8. Fitness Tracking App: Create an interface for fitness tracking services. Develop adapters for different fitness trackers or wearables.

  9. Recipe Management System: Design an interface for recipe storage and retrieval. Implement adapters for various recipe databases or APIs.


Recommended articles