Skip to content

Adapter

The Adapter pattern is used to adapt a certain object to the target interface. It requires introducing an intermediate layer that acts as a link between these objects. This connector should also implement the target interface.

We can use this pattern when:

  • we adjust the application that uses the old API to the new one.
  • we are integrating a new library which assumes that our objects implement a certain interface (which they do not, and we do not want or cannot rewrite the implementation of these objects).
  • we integrate many systems into one and we want certain groups of objects with a slightly different representation to use the same abstraction.

adapter

Example

The following example shows a simple adapter implementation. In this example, we can see:

  • the Student interface, which is our target interface (i.e. the one we want to work with)
  • the Pupil class, which is an object that does not match theStudent interface
  • the PupilAdapter class, which is an adapter, i.e. a connector, between theStudent and Pupil objects

Note that the object that has to be adapted comes as a constructor argument to the class representing the adapter. In the adapter, for the methods implementing the target interface, the programmer's task is to come up with a way to adjust the data structure to the expected format.

import java.util.Collection;

public interface Student {
  String getFullName();
  String getContactDetails();
  boolean isAdult();
  Collection<Integer> getResults();
}
import java.util.List;

public class Pupil {
  private final String firstName;
  private final String lastName;
  private final String email;
  private final Integer age;
  private final List<Integer> grades;

  public Pupil(final String firstName, final String lastName, final String email, final Integer age, final List<Integer> grades) {
    this.firstName = firstName;
    this.lastName = lastName;
    this.email = email;
    this.age = age;
    this.grades = grades;
  }

  public String getFirstName() {
    return firstName;
  }

  public String getLastName() {
    return lastName;
  }

  public String getEmail() {
    return email;
  }

  public Integer getAge() {
    return age;
  }

  public List<Integer> getGrades() {
    return grades;
  }
}

import java.util.Collection;

public class PupilAdapter implements Student {

  private final Pupil pupil;

  public PupilAdapter(final Pupil pupil) {
    this.pupil = pupil;
  }

  @Override
  public String getFullName() {
    return pupil.getFirstName() + " " + pupil.getLastName();
  }

  @Override
  public String getContactDetails() {
    return pupil.getEmail();
  }

  @Override
  public boolean isAdult() {
    return pupil.getAge() >= 18;
  }

  @Override
  public Collection<Integer> getResults() {
    return pupil.getGrades();
  }
}
import java.util.ArrayList;
import java.util.List;

public class AdapterUsage {
  public static void main(String[] args) {
    List<Student> students = new ArrayList<>();
    students.add(new PupilAdapter(new Pupil("Andrzej", "Nowak", "anowak@sda.pl", 19, List.of(3, 4, 5))));
    for (final var student : students) {
      System.out.println(student.getFullName()); // Andrzej Nowak
      System.out.println(student.getContactDetails()); // anowak@sda.pl
      System.out.println(student.getResults()); // [3, 4, 5]
      System.out.println(student.isAdult()); // true
    }
  }
}