The Adapter Factory

Step 5: The Adapter Factory

Finally, hide the wiring. Callers should ask for a processor by name, "stripe" or "paypal", and get back the correctly wrapped adapter, without importing adapter classes or knowing which SDK sits underneath. A small factory keeps adapter selection in one place.

Write get_processor(name, api): return a StripeAdapter around api for "stripe", a PayPalAdapter for "paypal", and raise ValueError for anything else. Together with the adapters, this is a complete unified payments layer over two incompatible SDKs.

  • get_processor(name, api). Return the adapter matching name, wrapping api; raise ValueError on an unknown name
Hints
Starter code
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):
    return processor.charge(amount)


def process_payment(processor, amount):
    result = processor.charge(amount)
    return "SUCCESS" if result["ok"] else "DECLINED"


def get_processor(name, api):
    """Return the adapter for name, wrapping api; ValueError if unknown."""
    # TODO: compare name against the two gateway names this factory knows and
    # build the matching adapter class around the api argument you were given.
    # Any other name is a configuration mistake, so raise ValueError for it
    # instead of quietly returning None.
    pass
Write it on a laptop

The editor and the test runner need a wide screen. Open this page on a desktop browser and your progress will be waiting.