Solid Principles Java
..
SOLID Principles Java with Explanation
SOLID principles are a set of design principles in object-oriented programming that help developers create more understandable, flexible, and maintainable software. They were introduced by Robert C. Martin and stand for:
-
Single Responsibility Principle (SRP)
-
Open/Closed Principle (OCP)
-
Liskov Substitution Principle (LSP)
-
Interface Segregation Principle (ISP)
-
Dependency Inversion Principle (DIP)
1. Single Responsibility Principle (SRP)
Definition: A class should have only one reason to change, meaning it should have only one job or responsibility. Example in Java:
class Book {
private String title;
private String author;
// Constructor, getters, and setters
public String getTitle() {
return title;
}
public String getAuthor() {
return author;
}
}
class BookPrinter {
public void print(Book book) {
System.out.println(book.getTitle() + " by " + book.getAuthor());
}
}
In this example, the Book class is responsible for storing book data, while the BookPrinter class handles printing the book details, adhering to SRP.
2. Open/Closed Principle (OCP)
Definition: Software entities (classes, modules, functions, etc.) should be open for extension but closed for modification. Example in Java:
abstract class Shape {
abstract void draw();
}
class Circle extends Shape {
void draw() {
System.out.println("Drawing a Circle");
}
}
class Square extends Shape {
void draw() {
System.out.println("Drawing a Square");
}
}
class Drawing {
public void drawShape(Shape shape) {
shape.draw();
}
}
In this example, new shapes can be added by extending the Shape class without modifying the existing code.
3. Liskov Substitution Principle (LSP)
Definition: Objects of a superclass should be replaceable with objects of a subclass without affecting the correctness of the program. Example in Java:
class Bird {
public void fly() {
System.out.println("Flying");
}
}
class Sparrow extends Bird {
// Inherits fly() method
}
class Ostrich extends Bird {
// Ostrich cannot fly, so it violates LSP if fly() is called on an Ostrich instance
}
To adhere to LSP, you might need to redesign the hierarchy:
abstract class Bird {
// No fly method
}
class FlyingBird extends Bird {
public void fly() {
System.out.println("Flying");
}
}
class Sparrow extends FlyingBird {
// Inherits fly() method
}
class Ostrich extends Bird {
// Does not have fly() method
}
4. Interface Segregation Principle (ISP)
Definition: Clients should not be forced to depend on interfaces they do not use. Example in Java:
interface Worker {
void work();
void eat();
}
class WorkerImpl implements Worker {
public void work() {
System.out.println("Working");
}
public void eat() {
System.out.println("Eating");
}
}
class Robot implements Worker {
public void work() {
System.out.println("Working");
}
public void eat() {
// Robots do not eat, violates ISP
}
}
To adhere to ISP:
interface Workable {
void work();
}
interface Eatable {
void eat();
}
class Worker implements Workable, Eatable {
public void work() {
System.out.println("Working");
}
public void eat() {
System.out.println("Eating");
}
}
class Robot implements Workable {
public void work() {
System.out.println("Working");
}
}
5. Dependency Inversion Principle (DIP)
Definition: High-level modules should not depend on low-level modules. Both should depend on abstractions (e.g., interfaces). Abstractions should not depend on details. Details should depend on abstractions. Example in Java:
class Light {
public void turnOn() {
System.out.println("Light is on");
}
public void turnOff() {
System.out.println("Light is off");
}
}
class Switch {
private Light light;
public Switch(Light light) {
this.light = light;
}
public void operate() {
light.turnOn();
}
}
To adhere to DIP:
interface Switchable {
void turnOn();
void turnOff();
}
class Light implements Switchable {
public void turnOn() {
System.out.println("Light is on");
}
public void turnOff() {
System.out.println("Light is off");
}
}
class Switch {
private Switchable device;
public Switch(Switchable device) {
this.device = device;
}
public void operate() {
device.turnOn();
}
}
These principles help in designing a system that is easier to manage and extend over time.
Leave a comment