SOLID Principles — An approach to code in better way
SOLID is a structured design approach that ensures your software is modular and easy to maintain, understand, debug and refactor.
It also helps to save time and effort in both development and maintenance
It prevents your code from becoming rigid and fragile, which helps you build long-lasting software.
Single Responsibility Principle
Each class should be responsible for a single part or functionality of the system
public class Vehicle{
public void printDetails() {}
public double calculateValue() {}
public void addVehicleToDB() {}
}
In the above example, Vehicle class has three responsibilities printing, calculating and database. Instead of having all responsibilities in single class we can create three classes with each responsibility
Open- Closed Principle
Software components should be open for extension, but not for modification
public class VehicleCalculations {
public double calculateValue(Vehicle v) {
if (v instanceof Car)
return v.getValue() * 0.8;
if (v instanceof Bike)
return v.getValue() * 0.5; }
}
In the above example, if suppose we want to add truck, we would have to modify the above class by adding another if statement, which goes against the principle.
Better approach would be for the subclasses Car and Truck to override the calculateValue() method
public class Vehicle {
public double calculateValue() {…}
}
public class Car extends Vehicle {
public double calculateValue() {
return this.getValue() * 0.8; } }public class Truck extends Vehicle{
public double calculateValue() {
return this.getValue() * 0.9; }}
Liskov Substitution principle
Objects of superclass should be replaceable with objects of its subclasses without breaking the system
public class Rectangle {
private double height;
private double width;
public void setHeight(double h) { height = h; }
public void setWidht(double w) { width = w; } …
}
public class Square extends Rectangle {
public void setHeight(double h) {
super.setHeight(h);
super.setWidth(h);
}
public void setWidth(double w) {
super.setHeight(w);
super.setWidth(w); }
}
}
In the above example, LSP principle is not satisfied. This is because Square has extra constriants that height and width should be same. So we cant replace the Rectangle with square
Interface Segregation Principle
No client should be forced to depend on methods that it does not use
public interface Vehicle {
public void drive();
public void stop();
public void refuel();
public void openDoors();
}
public class Bike implements Vehicle {
// Can be implemented
public void drive() {…}
public void stop() {…}
public void refuel() {…}
// Can not be implemented
public void openDoors() {…}
}
In the above example, Bike do not have the method openDoors but it is forced to implement it.
The interface can be broken down to multiple, small cohesive interfaces so that no class is forced to implement any interface and therefore methods, that it does not need.
Dependency Inversion Principle
High- level modules should not depend on low-level modules both should depend on abstractions.
The Dependency Inversion Principle (DIP) states that we should depend on abstractions (interfaces and abstract classes) instead of concrete implementations (classes). The abstractions should not depend on details; instead, the details should depend on abstractions.
public class Car {
private Engine engine;
public Car(Engine e) {
engine = e;
}
public void start() {
engine.start();
}
}
public class Engine {
public void start() {…}
}
In the above example, if we want to add another diesel engine it requires refactoring the Car Class
We can solve this by introducing a layer of abstraction.
Instead of Car depending directly on Engine, lets add an interface:
public interface Engine{
public void start();
}
Now we can connect any type of engine that implements the Engine interface to the Car class
public class Car {
private Engine engine;
public Car(Engine e) {
engine = e; }
public void start() {
engine.start();
}
}
public class PetrolEngine implements Engine {
public void start() {…}
}
public class DieselEngine implements Engine {
public void start() {…}
}