Sobes.tech
Middle

What is the difference between dependency injection and inversion of control?

sobes.tech AI

Answer from AI

Dependency Inversion Principle (DIP) is a design principle (part of S.O.L.I.D.). It states that:

  • 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.

Dependency Injection (DI) is a design pattern that implements the dependency inversion principle. It allows dependencies (objects that a class depends on) to be injected from outside, instead of the class creating them itself.

Main differences:

  • DIP is a principle, DI is a pattern that implements this principle.
  • DIP focuses on relationships between modules and abstractions/details.
  • DI focuses on ways to provide dependencies to an object.

Example without dependency inversion:

class Database {
    void save(Data data) {
        // Logic for saving to a specific database
    }
}

class Service {
    private Database database = new Database(); // Creating a specific dependency

    void saveData(Data data) {
        database.save(data);
    }
}

Here, Service (high-level module) directly depends on Database (low-level module). This violates DIP.

Example with dependency inversion (using dependency injection):

interface DataStorage { // Abstraction
    void save(Data data);
}

class Database implements DataStorage { // Detail depending on abstraction
    @Override
    void save(Data data) {
        // Logic for saving to a specific database
    }
}

class Service {
    private final DataStorage dataStorage; // Dependency on abstraction

    // Dependency injection via constructor
    public Service(DataStorage dataStorage) {
        this.dataStorage = dataStorage;
    }

    void saveData(Data data) {
        dataStorage.save(data);
    }
}

class Application {
    public static void main(String[] args) {
        DataStorage storage = new Database(); // Creating a specific implementation outside Service
        Service service = new Service(storage); // Injecting dependency
        // ...
    }
}

In this example, Service depends on the abstraction DataStorage, not on the concrete implementation Database. The concrete implementation Database is provided to Service from outside via the constructor (dependency injection). This complies with DIP and is implemented using DI.