SOLID PrinciplesDependency Inversion PrincipleMedium⏱️ ~3 min

Applying DIP: Parking Lot Payment System

Consider a parking lot system where the payment processor needs to charge customers and store transaction records. Without DIP, the high-level payment logic directly depends on specific payment gateway and database implementations.

Before (Violation)
ParkingPaymentService creates StripeClient and PostgresDB objects directly. Changing payment providers requires modifying business logic.
After (DIP Applied)
ParkingPaymentService depends on IPaymentGateway and ITransactionRepository. Implementations are injected at runtime.
ParkingPaymentService
- gateway: IPaymentGateway
- repository: ITransactionRepository
+ processPayment(ticket): Receipt
«interface»
IPaymentGateway
+ charge(amount, card): Result
StripeGateway
RazorpayGateway
«interface»
ITransactionRepository
+ save(transaction): Boolean
PostgresRepo
MongoRepo
Implementation Flow:
processPayment(ticket):
  fee = calculateFee(ticket.duration)
  result = gateway.charge(fee, ticket.card)
  if result.success:
    transaction = createTransaction(ticket, fee)
    repository.save(transaction)
    return createReceipt(transaction)
  else:
    throw PaymentFailedException
Benefits in This Design:
First, switching from Stripe to Razorpay requires zero changes to ParkingPaymentService. Only the concrete gateway implementation changes.

Second, testing becomes straightforward. Create MockPaymentGateway and InMemoryRepository implementations for unit tests without touching external services.

Third, the service can support multiple payment gateways simultaneously. A factory or strategy can select the appropriate implementation at runtime based on customer preference or region.

Fourth, database migration from PostgreSQL to MongoDB happens independently of business logic changes.
Interview Tip: Explain that the interfaces are defined in the same module as ParkingPaymentService, not in the gateway or repository modules. This package structure ensures the inversion.
💡 Key Takeaways
Business logic defines payment and storage contracts through interfaces
Concrete payment gateways and databases implement these contracts
Payment service logic remains unchanged when switching implementations
Testing uses mock implementations without modifying production code
Multiple implementations can coexist and be selected at runtime
📌 Examples
1Switching from Stripe to Razorpay without changing payment service code
2Adding MongoDB support alongside PostgreSQL for A/B testing
3Using in-memory repository for integration tests while production uses PostgreSQL
← Back to Dependency Inversion Principle Overview
Applying DIP: Parking Lot Payment System | Dependency Inversion Principle - System Overflow