Here is the payoff. Because both adapters honour the same target interface, client code can be written once and reused with any gateway. Write a checkout function that takes any PaymentProcessor and an amount, calls charge, and returns the result, with zero knowledge of whether it holds a Stripe or a PayPal adapter.
This is Adapter's promise: incompatible APIs made interchangeable behind one contract, so business logic depends on the interface, not on any specific SDK.
class StripeApi:
def create_charge(self, amount_cents):
if amount_cents <= 0:
return {"id": "ch_declined", "paid": False}
return {"id": "ch_" + str(amount_cents), "paid": True}
class PayPalApi:
def make_payment(self, dollars):
if dollars <= 0:
return {"success": False, "txn": "pp_declined"}
return {"success": True, "txn": "pp_" + str(dollars)}
class PaymentProcessor:
def charge(self, amount_dollars):
raise NotImplementedError
class StripeAdapter(PaymentProcessor):
def __init__(self, api):
self._api = api
def charge(self, amount_dollars):
cents = int(round(amount_dollars * 100))
resp = self._api.create_charge(cents)
return {"ok": resp["paid"], "id": resp["id"]}
class PayPalAdapter(PaymentProcessor):
def __init__(self, api):
self._api = api
def charge(self, amount_dollars):
resp = self._api.make_payment(amount_dollars)
return {"ok": resp["success"], "id": resp["txn"]}
def checkout(processor, amount):
"""Charge through any PaymentProcessor and return its result dict."""
# TODO:
# return processor.charge(amount)
pass
The editor and the test runner need a wide screen. Open this page on a desktop browser and your progress will be waiting.
Here is the payoff. Because both adapters honour the same target interface, client code can be written once and reused with any gateway. Write a checkout function that takes any PaymentProcessor and an amount, calls charge, and returns the result, with zero knowledge of whether it holds a Stripe or a PayPal adapter.
This is Adapter's promise: incompatible APIs made interchangeable behind one contract, so business logic depends on the interface, not on any specific SDK.
Press Run Tests or ββ© to check your solution.