SOLID Principles

 SOILD is acronym for five object oriented design principles by Robert Martin  aka Uncle Bob. These are principles promote good design practices and help developers write robust, flexible and maintainable code.

Each letter in SOILD represents one of the below principles.

  • Single Responsibility Principle (SRP): A class should have only one responsibility. 

public class FileHandler {

    public String readFile(String filePath) {

        // Code to read data from file

    }

    public void writeFile(String filePath, String data) {

        // Code to write data to file

    }

}

  • Open / Close Principle (OCP): A class should be open for extension but closed for modification. A new functionality can be added to class either by inheritance, interface or polymorphism without altering the existing code.
public abstract class Shape {
    public abstract double area();
}

public class Rectangle extends Shape {
    private double length;
    private double width;

    // Constructor, getters, and setters

    @Override
    public double area() {
        return length * width;
    }
}

public class Circle extends Shape {
    private double radius;

    // Constructor, getters, and setters

    @Override
    public double area() {
        return Math.PI * radius * radius;
    }
}
  • Liskov Substitution Principle (LSP) : A derived class or a sub class should be substitutable to its parent class or base class.

public class Bird {
    public void fly() {
        // Code for flying
    }
}

public class Duck extends Bird {
    @Override
    public void fly() {
        // Ducks can fly, so implement flying behaviour
    }
}
  • Interface Segregation Principle (ISP): We need to create specific interfaces for separate functionalities rather than creating a single interface with all functionalities.

public interface Printer {
    void print();
}

public interface Scanner {
    void scan();
}

public class MultiFunctionDevice implements Printer, Scanner {
    @Override
    public void print() {
        // Code to print
    }

    @Override
    public void scan() {
        // Code to scan
    }
}
  • Dependency Inversion Principle (DIP): High level modules should depend on abstraction not on low level modules. Also abstraction should not depend on details but details should depend on abstraction.
public interface DataService {
    String fetchData();
}

public class FileDataService implements DataService {
    @Override
    public String fetchData() {
        // Code to fetch data from a file
    }
}

public class DatabaseDataService implements DataService {
    @Override
    public String fetchData() {
        // Code to fetch data from a database
    }
}

public class DataProcessor {
    private DataService dataService;

    public DataProcessor(DataService dataService) {
        this.dataService = dataService;
    }

    public String processData() {
        String data = dataService.fetchData();
        // Process the data
        return processedData;
    }
}

The Dependency Inversion Principle is one of the five SOLID principles of object-oriented design. It states:

  1. High-level modules should not depend on low-level modules. Both should depend on abstractions.
  2. Abstractions should not depend on details. Details should depend on abstractions.

This principle suggests that we should rely on abstractions (interfaces or abstract classes) rather than concrete implementations. The idea is to reduce the coupling between different modules of a system, making the system more modular and easier to maintain or extend.

The Hollywood Principle is closely related to the idea of inversion of control, where instead of a traditional "calling" structure (where high-level components directly instantiate and use lower-level components), the framework or an external entity manages the flow of control. This is often summarized as "Don't call us, we'll call you."

Dependency Inversion vs. Dependency Injection

  • Dependency Inversion is a design principle that suggests that our code should depend on abstractions rather than concrete implementations.
  • Dependency Injection is a design pattern that helps achieve the Dependency Inversion Principle by injecting dependencies into a class rather than the class creating the dependencies itself.

How Dependency Inversion Can Be Achieved:

  • Observer Pattern: The observer pattern is a behavioral design pattern where an object (the subject) maintains a list of dependents (observers) and notifies them of state changes. This follows DIP because the subject depends on the abstraction of observers rather than concrete implementations.

  • Anonymous Functions, Lambdas, Method References: These can be used to inject behavior into classes without depending on concrete implementations, helping to decouple the components.

The Dependency Inversion Principle helps create a more flexible and decoupled system by inverting the traditional flow of dependencies, relying on abstractions rather than concrete implementations. Achieving DIP often involves patterns like Dependency Injection, and concepts like the Hollywood Principle, and can be implemented using various programming techniques.

ALSO
Dependency Inversion Principle: Abstraction should not depend on details while details should depend on abstraction. Its also called Hollywood principle. Don't call me I will call you. Instead of forward dependency, the dependency is reversed. A consumer instantiates a producer and calls the method. But in dependency inversion producer instantiates the consumer and calls the method, the dependency is reversed. Dependency Inversion can be achieved using observer pattern, anonymous function, lambda and method reference

Comments

Popular posts from this blog

Transform values with a stream

Collections Framework

Inspect a collection