Middle
What is the D letter in the SOLID principles?
sobes.tech AI
Answer from AI
Dependency Inversion Principle (DIP). 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.
This principle aims to reduce coupling between system components, making them more flexible and easier to test. Instead of direct dependence on specific implementations, components depend on interfaces or abstract classes.
Example without DIP:
// Low-level module
class Database {
public void save(String data) {
System.out.println("Saving data to database: " + data);
}
}
// High-level module depending on low-level
class DataProcessor {
private Database db = new Database(); // Direct dependency
public void processAndSave(String data) {
// Processing logic
db.save(data);
}
}
Example with DIP:
// Abstraction (interface)
interface DataSaver {
void save(String data);
}
// Low-level module depending on abstraction
class Database implements DataSaver {
@Override
public void save(String data) {
System.out.println("Saving data to database: " + data);
}
}
// Another possible low-level implementation
class FileSaver implements DataSaver {
@Override
public void save(String data) {
System.out.println("Saving data to file: " + data);
}
}
// High-level module depending on abstraction
class DataProcessor {
private final DataSaver dataSaver; // Dependency on abstraction
// Dependency injection via constructor
public DataProcessor(DataSaver dataSaver) {
this.dataSaver = dataSaver;
}
public void processAndSave(String data) {
// Processing logic
dataSaver.save(data); // Using abstraction
}
}
// Usage
class Main {
public static void main(String[] args) {
// High-level module does not depend on specific implementations of Database or FileSaver
// It depends on the DataSaver abstraction
DataSaver databaseSaver = new Database();
DataProcessor processor1 = new DataProcessor(databaseSaver);
processor1.processAndSave("Some important data");
DataSaver fileSaver = new FileSaver();
DataProcessor processor2 = new DataProcessor(fileSaver);
processor2.processAndSave("Another piece of data");
}
}
In the DIP example, DataProcessor (high-level module) depends on the DataSaver interface (abstraction), not on the concrete Database (low-level module). Database and FileSaver (details) depend on the same abstraction DataSaver. This allows easy swapping of low-level implementations without changing high-level modules.