Building Cloud Expertise with centron - Our Tutorials

Whether you are a beginner or an experienced professional, our practical tutorials provide you with the knowledge you need to make the most of our cloud services.

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)

Start Your Free Trial Today!

Unlock the full potential of your development process with our powerful cloud solutions. Experience seamless integration, enhanced performance, and unrivaled support. Sign up for a free trial now and discover how our cloud services can revolutionize your Java projects and beyond. Don't miss out – start your journey to the cloud today!

Try for free!