Паттерн Адаптер позволяет работать вместе классам с несовместимыми интерфейсами. Адаптер реализует интерфейс, ожидаемый клиентом, и переводит каждый вызов в адаптируемый класс. Так сторонние библиотеки подключают к своему коду, не давая их формам расползтись повсюду.
Проблема: несовместимые интерфейсы
Наш код оформления заказа хочет gateway.pay(amount, card). Платёжный SDK предлагает create_charge(cents, currency, source) и возвращает dict. Старый банковский API предлагает make_payment(euros, account_no) и возвращает "OK" или "FAIL". Править ни тот, ни другой нельзя.
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)'StripeLikeSdk' object has no attribute 'pay'Адаптер объекта
Адаптер хранит объект поставщика (композиция) и реализует наш интерфейс. Он переводит евро в центы, добавляет валюту и превращает результат поставщика в bool. Клиент не знает, какой поставщик стоит за pay.