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)
- class - where the adapter inherits from the target interface and the class of the adopted object
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 theStudent
interface - the
FavoriteAdapter
class, which is the adapter, i.e. a connector, between theStudent
andFavorite
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()