The SOLID principles are a set of guidelines that help developers design robust, maintainable, and scalable software systems. Introduced by Robert C. Martin, these principles are fundamental to object-oriented programming. Let’s explore each principle in detail:
A class should have one, and only one, reason to change. This means a class should only have one job or responsibility.
class Invoice {
void calculateTotal() {
// Calculation logic
}
void printInvoice() {
// Printing logic
}
}
// This violates SRP. The printing responsibility should be in another class.
Software entities (classes, modules, functions) should be open for extension but closed for modification.
interface Shape {
double area();
}
class Circle implements Shape {
double area() {
// Calculate area of circle
}
}
class Rectangle implements Shape {
double area() {
// Calculate area of rectangle
}
}
// New shapes can be added without modifying existing code.
Objects of a superclass should be replaceable with objects of a subclass without affecting the correctness of the program.
class Bird {
void fly() {
// Flying logic
}
}
class Penguin extends Bird {
void fly() {
throw new UnsupportedOperationException();
}
}
// This violates LSP. Penguin is not substitutable for Bird.
Clients should not be forced to depend on interfaces they do not use.
interface Animal {
void eat();
void fly(); // Violates ISP, as not all animals can fly.
}
interface Eatable {
void eat();
}
interface Flyable {
void fly();
}
// Segregating interfaces resolves the issue.
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.
interface Database {
void save(String data);
}
class MySQLDatabase implements Database {
void save(String data) {
// Save to MySQL
}
}
class Application {
Database database;
void storeData(String data) {
database.save(data);
}
}
// Application depends on abstraction, not implementation.