π What Youβll Learn
- What Dependency Inversion really means
- Why high-level modules shouldnβt depend on low-level ones
- Practical code examples
- How to apply DIP using interfaces and dependency injection
π What Is the Dependency Inversion Principle?
The Dependency Inversion Principle says:
High-level modules should not depend on low-level modules. Both should depend on abstractions.
Abstractions should not depend on details. Details should depend on abstractions.
In other words:
Depend on interfaces, not concrete implementations.
β A Typical Violation of DIP
public class LightBulb {
public void turnOn() { ... }
public void turnOff() { ... }
}
public class Switch {
private LightBulb bulb = new LightBulb();
public void operate() {
bulb.turnOn(); // tightly coupled
}
}
Here, Switch
depends directly on LightBulb
, a low-level module. Changing LightBulb
means modifying Switch
.
β Applying DIP with Abstraction
Introduce an interface:
public interface Switchable {
void turnOn();
void turnOff();
}
Now decouple:
public class LightBulb implements Switchable {
public void turnOn() { ... }
public void turnOff() { ... }
}
public class Switch {
private Switchable device;
public Switch(Switchable device) {
this.device = device;
}
public void operate() {
device.turnOn();
}
}
Now, Switch
depends on the abstraction Switchable
, not the concrete class.
π§ͺ Real-World Analogy: Payment Gateway
Imagine your app handles payments:
class PaymentService {
private PayPalAPI paypal = new PayPalAPI();
public void pay() {
paypal.sendMoney();
}
}
Tomorrow, you switch to Stripe. Thatβs a nightmare.
Better:
interface PaymentGateway {
void pay();
}
class PayPalGateway implements PaymentGateway { ... }
class StripeGateway implements PaymentGateway { ... }
class PaymentService {
private PaymentGateway gateway;
public PaymentService(PaymentGateway gateway) {
this.gateway = gateway;
}
public void processPayment() {
gateway.pay();
}
}
Now you can swap payment providers without rewriting business logic.
π§ Benefits of DIP
- π¦ Loose coupling
- π Easy to change implementations
- π§ͺ Better testability (mocks, stubs)
- π§ Cleaner architecture
π Recap
- DIP = Rely on abstractions, not concrete implementations
- Both high-level and low-level modules should depend on interfaces
- Enables flexibility, testability, and long-term maintainability
π Wrapping Up the SOLID Series
Congratulations! You've now learned:
- Single Responsibility Principle
- Open/Closed Principle
- Liskov Substitution Principle
- Interface Segregation Principle
- Dependency Inversion Principle
You're on the path to writing clean, robust, and scalable object-oriented code.