SOLID Principles in Java

Deepika sharma
Nerd For Tech
Published in
3 min readJul 10, 2021

SOLID principles basically form the fundamental guidelines for building object-oriented , loosely coupled , robust, maintainable and easily understandable applications . One of the most frequently asked interview questions, lets look at each one of them:

Single Responsibility : A class should have one and only one responsibility. We should write, change or maintain a class for only one purpose which gives us the advantage of cleaner ,robust code and fewer test cases as to we know which functionality is covered in which class and which class would be modified in case of a change. For ex:
public class Vehicle{
public void printDetails() {}
public double calculate() {}
public void addtoDB() {}
}

Above class has three separate responsibilities: printing, calculation and adding to database. By applying SRP, we can separate the above class into three classes with separate responsibilities.

Open Closed : A class should be open for extension but closed for modification which essentially means we do not want our existing code to be modified causing potential issues or bugs . Other developers incase of some functionality change should be able to extend our class and override some methods. For ex:
public class VehiclePrice {
public double Value(Vehicle v) {
if (v instanceof Car) {
return v.getValue() * 0.5;
if (v instanceof Truck) {
return v.getValue() * 0.8;
}
}
If we want to add one more type to this ,say e-bike, we would have to modify the above class with one more if statement which goes against the principle. A better way is to let the sub classes override the Value method as per their type.

Liskov Substitution : Derived classes must be substitutable for the base class. In simple words, If class A is extending class B, we should be able to replace B with A, without disrupting the behavior of our program. As per OOPS concepts inheritance is a good practice but Liskov principle mandates to use inheritance with a careful consideration. We should only use inheritance if our super class is replaceable with a sub class in all the instances.
For ex: Classic Square Rectangle problem.
public class Rectangle {
private double height;
private double width;
public void setHeight(double h) { height = h; }
public void setWidht(double w) { width = w; }
//getters and calculateArea method
}
public class Square extends Rectangle {
public void setHeight(double h) {
super.setHeight(h);
super.setWidth(w);
}
public void setWidth(double h) {
super.setHeight(h);
super.setWidth(w);
}
}
As its clear base class Rectangle is clearly not replaceable by sub class Square , as square has a constraint of equal height and width, so substituting Rectangle class with Square class breaks LSP.

Interface Segregation : No one should be required to implement methods in their classes which they will not use. Larger interfaces should be split into smaller ones. This ensures that implementing classes only need to be concerned about the methods that are useful to them. This gives us flexibility to use only the required functionality. For ex:
public interface Vehicle {
public void drive();
public void stop();
public void openDoors();
}
public class Bike implements Vehicle {
// Can be implemented
public void drive() {...}
public void stop() {...}
// Can not be implemented
public void openDoors() {...}
}
For a bike class to implement openDoors method does not make sense. This should be fixed by breaking the Vehicle interface to multiple smaller interfaces with likely functionality so as no class is forced to implement non required methods.

Dependency Inversions : A class should depend on abstraction(interfaces and abstract classes) and not on concretion (classes).
public class Car {
private Engine engine;
public Car(Engine e) {
engine = e;
}
public void start() {
engine.start();
}
}
public class Engine {
public void start() { //some implementation }
}
Above code will work for one engine but what if there are two types of engine, say diesel and petrol, it would mean to modify our class which is not good idea.
This can be solved by adding a abstraction layer , so car instead of directly depending on Engine now depends on EngineInterface. PetrolEngine or DieselEngine classes implement this interface and we can connect any of these to the Car class:

Hope this article gives a good idea on SOLID principles. Happy Learning :)
.
.
References : educative.io , howToDoInJava

--

--