Skip to content

Adapter

The ʻAdapter` design pattern is used to match a certain object to a target interface. It requires us to introduce a intermediate layer that acts as a link between these objects. This connector should also implement the target interface.

We can use this pattern, for example, when:

  • we adjust the application using the old API to the new one.
  • we integrate a new library that 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.

The adapter pattern can be implemented in two ways:

  • object-oriented - where the adapter object aggregates the adopted object (has a reference to it)

adapter

  • class - where the adapter inherits from the target interface and the class of the adopted object

adapter

Example

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

  • the Student interface, which is our target interface (the one we want to work with)
  • the Favorite class, which is currently not compatible with the Student interface
  • the FavoriteAdapter class, which is the adapter, i.e. a connector, between the Student and Favorite objects

In the object version the object to be adapted (class Favorite) comes as an argument of the method __init__ to the class representing the adapter (FavoriteAdapter), in the class version the class representing the adapter (FavoriteAdapter) inherits from it and from the target interface (Student). In the methods implementing the target interface, the programmer's task is to figure out a way to match the data structure to the expected format.

Implementation - object-oriented version

class Student:
    def get_full_name(self):
        pass

    def get_contact_details(self):
        pass

    def is_adult(self):
        pass

    def get_results(self):
        pass
class Favorite:
    def __init__(self, first_name, last_name, email, age, grades):
        self._first_name = first_name
        self._last_name = last_name
        self._email = email
        self._age = age
        self._grades = grades

    def get_first_name(self):
        return self._first_name

    def get_last_name(self):
        return self._last_name

    def get_email(self):
        return self._email

    def get_age(self):
        return self._age

    def get_grades(self):
        return self._grades
class FavoriteAdapter(Student):
    def __init__(self, Favorite):
        self._Favorite = Favorite

    def get_full_name(self):
        return self._Favorite.get_first_name() + " " + self._Favorite.get_last_name()

    def get_contact_details(self):
        return self._Favorite.get_email()

    def is_adult(self):
        return self._Favorite.get_age() >= 18

    def get_results(self):
        return self._Favorite.get_grades()
def main():
    students = [FavoriteAdapter(Favorite('Steven', 'Morgan', 'sm@gmail.com', 19, [3, 4, 5])),
                FavoriteAdapter(Favorite('Maria', 'Smith', 'mk@hotmail.com', 17, [4, 5, 4])),
                FavoriteAdapter(Favorite('Joanna', 'Noris', 'jn@yahoo.com', 21, [2, 4, 6]))]

    for s in students:
        print(f"{'Adult' if s.is_adult() else 'Child'} {s.get_full_name()} [{s.get_contact_details()}]: {s.get_results()}")


if __name__ == '__main__':
    main()

Implementation - class version

class Student:
    def get_full_name(self):
        pass

    def get_contact_details(self):
        pass

    def is_adult(self):
        pass

    def get_results(self):
        pass
class Favorite:
    def __init__(self, first_name, last_name, email, age, grades):
        self._first_name = first_name
        self._last_name = last_name
        self._email = email
        self._age = age
        self._grades = grades

    def get_first_name(self):
        return self._first_name

    def get_last_name(self):
        return self._last_name

    def get_email(self):
        return self._email

    def get_age(self):
        return self._age

    def get_grades(self):
        return self._grades
class FavoriteAdapter(Student, Favorite):
    def __init__(self, first_name, last_name, email, age, grades):
        super().__init__(first_name, last_name, email, age, grades)

    def get_full_name(self):
        return self.get_first_name() + " " + self.get_last_name()

    def get_contact_details(self):
        return self.get_email()

    def is_adult(self):
        return self.get_age() >= 18

    def get_results(self):
        return self.get_grades()
def main():
    students = [FavoriteAdapter('Steven', 'Morgan', 'sm@gmail.com', 19, [3, 4, 5]),
                FavoriteAdapter('Maria', 'Smith', 'mk@hotmail.com', 17, [4, 5, 4]),
                FavoriteAdapter('Joanna', 'Noris', 'jn@yahoo.com', 21, [2, 4, 6])]

    for s in students:
        print(f"{'Adult' if s.is_adult() else 'Child'} {s.get_full_name()} [{s.get_contact_details()}]: {s.get_results()}")


if __name__ == '__main__':
    main()