Skip to content

The Adapter Design Pattern in Java

Posted on:September 6, 2022 at 01:13 PM

In the realm of design patterns, the Adapter pattern stands as one of the simplest and most intuitive in the structural category. This pattern excels in bridging the gap between different interfaces, making it easier for systems to communicate seamlessly. Let’s delve into the workings of the Adapter pattern and how it can be effectively implemented in Java.

Table of contents

Open Table of contents

Sections

What is the Adapter Pattern?

The Adapter pattern plays a crucial role in converting one interface of a class into another interface that a client expects. This is immensely useful when integrating legacy code or third-party libraries into a current project. Often, inconsistencies exist between the interfaces of these different systems, and the Adapter pattern comes to the rescue by harmonizing them.

Imagine a scenario where we have some legacy code with specific functionality we want to use in our current project. However, due to interface inconsistencies, direct use of this functionality is not feasible. This is where the Adapter pattern shines—it allows us to convert data or interfaces, ensuring smooth communication between systems.

To visualize this, consider a client working on a project with a specific target call. The client needs to access a specific call in some legacy code, but the correct interface for direct communication is missing. The Adapter pattern acts as a bridge, converting the client’s call to match the third-party system’s specific call, facilitating effective communication.

factoryUML

Implementing the Adapter Pattern

Let’s proceed to implement the Adapter pattern in Java using a simple example.

Step 1: Define Third-Party Data Type

First, we assume a third-party data type, let’s call it DisplayDataThirdParty, which cannot be modified. This data type has two parameters: index (float) and someData (string).

public class DisplayDataThirdParty {
    public float index;
    public String someData;

    public DisplayDataThirdParty(float index, String someData) {
        this.index = index;
        this.someData = someData;
    }

    public void displayData() {
        System.out.println("Data is displayed: " + index + " - " + someData);
    }
}

Step 2: Define Current Data Type

Next, we define a current data type, DatabaseData, which is assumed to be part of our system. This data type also has two parameters: position (int) and amount (int).

public class DatabaseData {
    public int position;
    public int amount;

    public DatabaseData(int position, int amount) {
        this.position = position;
        this.amount = amount;
    }
}

For simplicity, we’ll create a DatabaseDataGenerator class to generate example data for DatabaseData.

Step 3: Create an Adapter Interface

Now, let’s create an adapter interface, DatabaseDataAdapter, that defines a method to convert DatabaseData to DisplayDataThirdParty.

public interface DatabaseDataAdapter {
    List<DisplayDataThirdParty> convertData(List<DatabaseData> data);
}

Step 4: Implement the Adapter

We’ll then implement the adapter, DatabaseDataAdapterImpl, which converts DatabaseData to DisplayDataThirdParty.

public class DatabaseDataAdapterImpl implements DatabaseDataAdapter {
    @Override
    public List<DisplayDataThirdParty> convertData(List<DatabaseData> data) {
        List<DisplayDataThirdParty> result = new ArrayList<>();

        for (DatabaseData datum : data) {
            DisplayDataThirdParty displayData = new DisplayDataThirdParty(datum.position, Integer.toString(datum.amount));
            result.add(displayData);
        }

        return result;
    }
}

Step 5: Utilize the Adapter

Finally, let’s create a client that uses the adapter to convert and display the data.

public class Client {
    public static void main(String[] args) {
        // Generate example database data
        DatabaseDataGenerator generator = new DatabaseDataGenerator();
        List<DatabaseData> databaseData = generator.generateData();

        // Create the adapter and convert data
        DatabaseDataAdapter adapter = new DatabaseDataAdapterImpl();
        List<DisplayDataThirdParty> legacyData = adapter.convertData(databaseData);

        // Display the converted data
        for (DisplayDataThirdParty data : legacyData) {
            data.displayData();
        }
    }
}

Conclusion

The Adapter pattern is a versatile design pattern that allows seamless integration of disparate systems by bridging the interface gap. By converting one interface into another, it facilitates effective communication between components, making it a valuable tool in software development. Understanding and implementing the Adapter pattern can significantly enhance code reusability and maintainability.

In this article, we explored the fundamentals of the Adapter pattern and presented a practical example of its implementation in Java. Incorporating the Adapter pattern into your software architecture can open doors to smoother integration and more efficient communication between systems.

Happy coding!