Card 03/ 09

ExampleDifficulty: Intermediate1 min

One Loop Over Three Payment Methods

A refund run over yesterday's failed orders. Each order was paid in a different way, and each way of paying knows how to reverse itself.

java
interface PaymentMethod { Receipt refund(BigDecimal amount); }

class Card implements PaymentMethod {
    public Receipt refund(BigDecimal amount) { return gateway.reverse(token, amount); }
}
class BankTransfer implements PaymentMethod {
    public Receipt refund(BigDecimal amount) { return bank.credit(iban, amount); }
}
class StoreCredit implements PaymentMethod {
    public Receipt refund(BigDecimal amount) { return wallet.topUp(userId, amount); }
}
java
for (Order order : failedYesterday) {
    Receipt receipt = order.paymentMethod().refund(order.total());
    audit.record(receipt);
}

Three completely different things happen on line 2 — a call to a card gateway, a bank credit, a wallet top-up — and the loop names none of them. Adding a fourth way to pay adds a class and changes nothing here.

Put this beside the shapes and the shared structure comes out, which is worth stating rather than leaving to be noticed: in both, one variable's declared type names a capability, the objects behind it are several different classes, and neither loop contains a single if. The domains have nothing in common; the mechanism is identical.