100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace

What is the Dependency Inversion Principle?

Understand the Dependency Inversion Principle (SOLID) — depending on abstractions, not concrete classes — with a Java example.

mediumQ48 of 226 in Object Oriented Programming Est. time: 5 minsLast updated:
Open Code Lab

Expected Interview Answer

The Dependency Inversion Principle (the 'D' in SOLID) states that high-level modules should not depend on low-level modules — both should depend on abstractions, and abstractions should not depend on details.

In practice this means a business-logic class should depend on an interface like NotificationSender rather than directly on a concrete EmailSender class, and the concrete implementation is supplied from outside, typically via constructor injection. This inverts the naturally expected dependency direction: instead of high-level policy code depending downward on low-level detail code, both depend on a shared abstraction owned closer to the high-level module. DIP is the principle that makes dependency injection frameworks meaningful, and it is what allows swapping implementations (a real email sender for a test double) without touching the high-level class. It is distinct from simply 'using interfaces' — the key is which side defines and owns the abstraction.

  • Decouples business logic from concrete implementation details
  • Makes unit testing easy via mockable abstractions
  • Allows swapping implementations without changing high-level code
  • Enables plugin-style architectures and dependency injection

AI Mentor Explanation

A team captain plans strategy around the abstract role of 'opening bowler' rather than depending on one specific named bowler, so if that player is injured, any player who fulfills the opening-bowler role can step in without changing the game plan. The captain’s high-level strategy depends on the role, not the concrete individual, and the individual is chosen and slotted in from outside. That is dependency inversion: high-level strategy depends on an abstraction, and the concrete detail is supplied afterward.

Step-by-Step Explanation

  1. Step 1

    Identify the high-level policy

    Find the business-logic class that currently instantiates or calls a concrete low-level class directly.

  2. Step 2

    Extract an abstraction

    Define an interface expressing the capability the high-level class actually needs (e.g. NotificationSender).

  3. Step 3

    Make the low-level class implement it

    The concrete detail class (EmailSender) implements the interface owned by/near the high-level side.

  4. Step 4

    Inject the dependency

    Supply the concrete implementation to the high-level class via constructor/setter injection rather than the class creating it itself.

What Interviewer Expects

  • Correct statement: both high- and low-level modules depend on abstractions
  • A concrete example distinguishing "depends on interface" from "depends on concrete class"
  • Awareness that DIP enables dependency injection and testability
  • Distinction from simple abstraction/polymorphism — DIP is about the direction of dependency

Common Mistakes

  • Confusing Dependency Inversion with Dependency Injection (DI is a technique that implements DIP)
  • Saying "just use an interface" without explaining which side owns the abstraction
  • Not mentioning that abstractions should not depend on low-level details
  • Giving an example where the high-level class still calls new ConcreteClass() itself

Best Answer (HR Friendly)

Dependency Inversion means my important business logic should depend on an abstraction, like an interface, rather than on a specific concrete implementation. So instead of my order-processing code creating a specific EmailSender itself, it depends on a NotificationSender interface, and the actual implementation gets passed in from outside. That makes it easy to swap implementations and to test the logic with a fake version.

Code Example

Depending on an abstraction instead of a concrete class
// Violates DIP: high-level class depends directly on a low-level concrete class
class OrderService {
    private EmailSender sender = new EmailSender();
    void placeOrder() {
        sender.send("Order confirmed");
    }
}

// Following DIP: both depend on an abstraction
interface NotificationSender {
    void send(String message);
}

class EmailSender implements NotificationSender {
    public void send(String message) { System.out.println("Email: " + message); }
}

class SmsSender implements NotificationSender {
    public void send(String message) { System.out.println("SMS: " + message); }
}

class OrderServiceGood {
    private final NotificationSender sender;
    OrderServiceGood(NotificationSender sender) { this.sender = sender; } // injected
    void placeOrder() {
        sender.send("Order confirmed");
    }
}

Follow-up Questions

  • How does Dependency Inversion differ from Dependency Injection?
  • Which side should own the abstraction in a DIP-compliant design?
  • How does DIP improve unit testability?
  • Can you have DIP without a dependency injection framework?

MCQ Practice

1. The Dependency Inversion Principle states that?

DIP requires both high-level and low-level modules to depend on shared abstractions, not on each other directly.

2. Dependency Injection relates to DIP as?

Dependency Injection is a practical mechanism (constructor/setter injection) commonly used to satisfy DIP.

3. A class instantiating its dependency with new ConcreteClass() internally is a sign of?

Directly instantiating a concrete dependency ties the high-level class to a low-level detail, violating DIP.

Flash Cards

Dependency Inversion Principle in one line?High-level and low-level modules should both depend on abstractions, not on each other directly.

Common implementing technique?Dependency injection (constructor or setter injection).

Key benefit?Implementations can be swapped or mocked without changing high-level code.

DIP vs DI?DIP is the design principle; DI is a technique commonly used to achieve it.

1 / 4

Continue Learning