Applying Abstraction: Parking Lot Payment System
Consider designing a parking lot that accepts multiple payment methods. Abstraction allows the ParkingLot to process payments without knowing specific payment implementation details.
+ charge(amount): PaymentResult
+ refund(transactionId): Boolean
- cvv
+ charge()
+ refund()
- appToken
+ charge()
+ refund()
+ charge()
+ refund()
- paymentMethod: PaymentMethod
- amount: Money
+ issueReceipt(): Receipt
Design Decision Rationale:
First, the PaymentMethod interface abstracts payment processing. The ParkingTransaction depends on the interface, not concrete implementations. This follows the Dependency Inversion Principle (DIP), where high-level modules depend on abstractions.
Second, each payment type implements the interface differently. CreditCard communicates with a payment gateway, MobileWallet uses OAuth tokens, and Cash simply validates the tendered amount. The ParkingTransaction remains unchanged when adding new payment methods like cryptocurrency or gift cards.
Third, the interface defines a complete contract with authorize(), charge(), and refund(). This ensures all payment methods support the full payment lifecycle. If a payment type does not support refunds (like some prepaid cards), it should throw an UnsupportedOperationException rather than silently fail, but this is a design trade-off discussed in advanced scenarios.
PaymentMethod interface. Interviewers value seeing proper abstraction over implementing every payment detail.