DEV Community

DevCorner
DevCorner

Posted on

Dependency Inversion, Dependency Injection, and Inversion of Control in Architectural Patterns & Software Architecture

These three concepts—Dependency Inversion Principle (DIP), Dependency Injection (DI), and Inversion of Control (IoC)—are fundamental to designing maintainable and scalable software. While they are related, they serve different purposes in software design and architecture.


1. Dependency Inversion Principle (DIP) – A Design Principle

📌 What is it?

Dependency Inversion is one of the SOLID principles of object-oriented design. 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.

🔹 Category: Design Principle (Part of SOLID)

🔹 Example in Code (Without DIP):

class MySQLDatabase {
    public void connect() {
        System.out.println("Connecting to MySQL...");
    }
}

class UserService {
    private MySQLDatabase db = new MySQLDatabase(); // Tight Coupling ❌

    public void getUser() {
        db.connect();
        System.out.println("Fetching user...");
    }
}
Enter fullscreen mode Exit fullscreen mode

Problem: UserService is tightly coupled to MySQLDatabase. If we want to switch to PostgreSQL or MongoDB, we need to modify the UserService class.

🔹 Applying DIP (Using Interface & Abstraction):

interface Database {
    void connect();
}

class MySQLDatabase implements Database {
    public void connect() {
        System.out.println("Connecting to MySQL...");
    }
}

class PostgreSQLDatabase implements Database {
    public void connect() {
        System.out.println("Connecting to PostgreSQL...");
    }
}

class UserService {
    private Database db; // Depends on abstraction ✅

    public UserService(Database db) {
        this.db = db;
    }

    public void getUser() {
        db.connect();
        System.out.println("Fetching user...");
    }
}
Enter fullscreen mode Exit fullscreen mode

Now, UserService depends on an abstraction (Database) instead of a concrete implementation (MySQLDatabase).

We can inject any database implementation at runtime without modifying the UserService class.


2. Dependency Injection (DI) – A Design Pattern

📌 What is it?

Dependency Injection (DI) is a design pattern that implements Dependency Inversion Principle by injecting dependencies rather than creating them inside a class.

🔹 Category: Design Pattern (Creational Pattern)

🔹 Types of DI:

  • Constructor Injection (Most recommended)
  • Setter Injection
  • Field Injection (Not recommended)

🔹 Example in Spring Boot (Constructor Injection):

@Component
class MySQLDatabase implements Database {
    public void connect() {
        System.out.println("Connecting to MySQL...");
    }
}

@Service
class UserService {
    private final Database db;

    @Autowired
    public UserService(Database db) { // Constructor Injection ✅
        this.db = db;
    }

    public void getUser() {
        db.connect();
        System.out.println("Fetching user...");
    }
}
Enter fullscreen mode Exit fullscreen mode

Spring automatically injects the Database dependency at runtime.

Benefits of DI:
✅ Reduces tight coupling

✅ Improves testability (easy to mock dependencies)

✅ Makes code more maintainable


3. Inversion of Control (IoC) – An Architectural Pattern

📌 What is it?

Inversion of Control (IoC) is a broader architectural pattern where the control of object creation and dependency management is given to a framework (like Spring) rather than being manually managed by the developer.

🔹 Category: Architectural Pattern

🔹 IoC is implemented using DI (Dependency Injection is one of the techniques to achieve IoC).

🔹 Example in Spring Boot:

@Configuration
@ComponentScan("com.example")
public class AppConfig {
    // Spring handles object creation
}
Enter fullscreen mode Exit fullscreen mode

Here, Spring manages object creation and injects dependencies automatically.

IoC Containers in Spring:

ApplicationContext

BeanFactory


Summary

Concept Type Purpose Example
Dependency Inversion Principle (DIP) Design Principle (SOLID) Code should depend on abstractions, not concrete implementations Interfaces & abstractions instead of direct dependencies
Dependency Injection (DI) Design Pattern (Creational) Inject dependencies instead of creating them inside a class Constructor, Setter, Field Injection
Inversion of Control (IoC) Architectural Pattern Framework controls object creation and lifecycle Spring IoC Container

Conclusion

  • DIP is a principle that guides software design.
  • DI is a pattern that implements DIP in a structured way.
  • IoC is an architectural concept that frameworks like Spring use to manage objects.

Would you like me to add more details on a specific topic? 🚀

Top comments (0)