Connect Incompatible Interfaces in Java with the Adapter Design Pattern

Learn how the Adapter Design Pattern in Java harmoniously brings together incompatible interfaces. Discover realistic applications and implementations of this useful pattern, from mobile chargers to Java classes.

A Real-Life Example

A great real-life example of the Adapter Design Pattern is a mobile charger. The mobile battery requires 3 volts to charge, but the regular socket provides either 120 volts (USA) or 240 volts (India). So, the mobile charger acts as an adapter between the mobile charging port and the wall socket.

Implementation of a Multi-Adapter

We will attempt to implement a multi-adapter using the Adapter Design Pattern in this tutorial. To do this, we will need two classes initially: Volt (to measure volts) and Socket (to generate a constant 120 volts).

package com.journaldev.design.adapter;

public class Volt {

    private int volts;

    public Volt(int v) {
        this.volts = v;
    }

    public int getVolts() {
        return volts;
    }

    public void setVolts(int volts) {
        this.volts = volts;
    }
}

package com.journaldev.design.adapter;

public class Socket {

    public Volt getVolt() {
        return new Volt(120);
    }
}

Create an Adapter Interface

Now, let’s create an adapter that can produce 3 volts, 12 volts, and default 120 volts. For this purpose, we create an adapter interface with these methods:

package com.journaldev.design.adapter;

public interface SocketAdapter {

    public Volt get120Volt();

    public Volt get12Volt();

    public Volt get3Volt();
}

There are two approaches to implementing the Adapter Pattern: the class adapter and the object adapter. However, both approaches achieve the same result.

Class Adapter – Implementation

Here is the implementation of the class adapter:

package com.journaldev.design.adapter;

// Using inheritance for the Adapter pattern
public class SocketClassAdapterImpl extends Socket implements SocketAdapter {

    @Override
    public Volt get120Volt() {
        return getVolt();
    }

    @Override
    public Volt get12Volt() {
        Volt v = getVolt();
        return convertVolt(v, 10);
    }

    @Override
    public Volt get3Volt() {
        Volt v = getVolt();
        return convertVolt(v, 40);
    }

    private Volt convertVolt(Volt v, int i) {
        return new Volt(v.getVolts() / i);
    }
}

Object Adapter – Implementation

Here is the implementation of the object adapter:

package com.journaldev.design.adapter;

public class SocketObjectAdapterImpl implements SocketAdapter {

    // Using composition for the Adapter pattern
    private Socket sock = new Socket();

    @Override
    public Volt get120Volt() {
        return sock.getVolt();
    }

    @Override
    public Volt get12Volt() {
        Volt v = sock.getVolt();
        return convertVolt(v, 10);
    }

    @Override
    public Volt get3Volt() {
        Volt v = sock.getVolt();
        return convertVolt(v, 40);
    }

    private Volt convertVolt(Volt v, int i) {
        return new Volt(v.getVolts() / i);
    }
}

Note that both adapter implementations are nearly identical and can implement the SocketAdapter interface. The adapter interface can also be an abstract class.

Test Program

Here is a test program to use our Adapter Design Pattern implementation:

package com.journaldev.design.test;

import com.journaldev.design.adapter.SocketAdapter;
import com.journaldev.design.adapter.SocketClassAdapterImpl;
import com.journaldev.design.adapter.SocketObjectAdapterImpl;
import com.journaldev.design.adapter.Volt;

public class AdapterPatternTest {

    public static void main(String[] args) {

        testClassAdapter();
        testObjectAdapter();
    }

    private static void testObjectAdapter() {
        SocketAdapter sockAdapter = new SocketObjectAdapterImpl();
        Volt v3 = getVolt(sockAdapter, 3);
        Volt v12 = getVolt(sockAdapter, 12);
        Volt v120 = getVolt(sockAdapter, 120);
        System.out.println("v3 volts using Object Adapter=" + v3.getVolts());
        System.out.println("v12 volts using Object Adapter=" + v12.getVolts());
        System.out.println("v120 volts using Object Adapter=" + v120.getVolts());
    }

    private static void testClassAdapter() {
        SocketAdapter sockAdapter = new SocketClassAdapterImpl();
        Volt v3 = getVolt(sockAdapter, 3);
        Volt v12 = getVolt(sockAdapter, 12);
        Volt v120 = getVolt(sockAdapter, 120);
        System.out.println("v3 volts using Class Adapter=" + v3.getVolts());
        System.out.println("v12 volts using Class Adapter=" + v12.getVolts());
        System.out.println("v120 volts using Class Adapter=" + v120.getVolts());
    }

    private static Volt getVolt(SocketAdapter sockAdapter, int i) {
        switch (i) {
            case 3:
                return sockAdapter.get3Volt();
            case 12:
                return sockAdapter.get12Volt();
            case 120:
                return sockAdapter.get120Volt();
            default:
                return sockAdapter.get120Volt();
        }
    }
}

When we run the above test program, we get the following output:

v3 volts using Class Adapter=3
v12 volts using Class Adapter=12
v120 volts using Class Adapter=120
v3 volts using Object Adapter=3
v12 volts using Object Adapter=12
v120 volts using Object Adapter=120

Summary

The Adapter Design Pattern allows two unrelated interfaces to work together by placing an adapter object between them. In this blog post, we have seen how the Adapter Pattern can be implemented in Java, both as a class adapter and as an object adapter. This design pattern is particularly useful when dealing with legacy code or third-party interfaces.

Examples in the JDK

Some examples of the Adapter Design Pattern in JDK classes are:

  • java.util.Arrays#asList()
  • java.io.InputStreamReader(InputStream) (returns a Reader)
  • java.io.OutputStreamWriter(OutputStream) (returns a Writer)

Create a Free Account

Register now and get access to our Cloud Services.

Posts you might be interested in:

centron Managed Cloud Hosting in Deutschland

Hibernate SessionFactory

JavaScript, Tutorial
Hibernate SessionFactory Hibernate SessionFactory is the factory class through which we get sessions and perform database operations. Content1 Hibernate SessionFactory2 Conclusion Hibernate SessionFactory Hibernate SessionFactory provides three methods through which…