Паттерн Адаптер позволяет работать вместе классам с несовместимыми интерфейсами. Адаптер реализует интерфейс, ожидаемый клиентом, и переводит каждый вызов в адаптируемый класс. Так сторонние библиотеки подключают к своему коду, не давая их формам расползтись повсюду.

Проблема: несовместимые интерфейсы

Наш код оформления заказа хочет gateway.pay(amount, card). Платёжный SDK предлагает create_charge(cents, currency, source) и возвращает dict. Старый банковский API предлагает make_payment(euros, account_no) и возвращает "OK" или "FAIL". Править ни тот, ни другой нельзя.

python
class StripeLikeSdk:                  # third-party code, we cannot edit it
    def create_charge(self, cents, currency, source):
        return {"id": "ch_1", "status": "succeeded", "amount": cents}

class OldBankApi:                     # another vendor, another shape
    def make_payment(self, euros, account_no):
        return "OK" if euros > 0 else "FAIL"

def checkout(gateway, amount, card):
    print("paid" if gateway.pay(amount, card) else "declined")

try:
    checkout(StripeLikeSdk(), 12.5, "tok_1")
except AttributeError as e:
    print(e)
text
'StripeLikeSdk' object has no attribute 'pay'

Адаптер объекта

Адаптер хранит объект поставщика (композиция) и реализует наш интерфейс. Он переводит евро в центы, добавляет валюту и превращает результат поставщика в bool. Клиент не знает, какой поставщик стоит за pay.