Java Day2 Java Solid Principal
Java Day2 Java Solid Principal
Java Day2 Java Solid Principal
Prepared for:
Contributor:
Contents
1. Solid Principal in Java..................................................................................................................................3
1.1 Single Responsibility Principle (SRP)................................................................................................3
1.2 Open/Closed Principle (OCP)..........................................................................................................4
1.3 Liskov Substitution Principle (LSP)...................................................................................................6
1.4 Interface Segregation Principle (ISP)...............................................................................................8
1.5 Dependency Inversion Principle (DIP).............................................................................................9
2. Single Responsibility Principle (SRP) – Example........................................................................................11
2.1 Explanation:..................................................................................................................................12
2.2 Compile and Run...........................................................................................................................12
1. Solid Principal in Java
SOLID principle is an acronym that stands for 5 key principles in
software development:
S – Single Responsibility Principle
O – Open Closed Principle
L – Liskov Substitution Principle
I – Interface Segregation Principle
D – Dependency Inversion Principle
Definition: A class should have only one reason to change, meaning it should have only one job or
responsibility.
If a waiter started cooking or a chef started handling payments, it would violate the SRP. Each role
has a single responsibility.
1.2 Open/Closed Principle (OCP)
Definition: Software entities should be open for extension but closed for modification.
The design of a plug socket is fixed and doesn't change. However, you can extend its
functionality by plugging in different devices (lamps, chargers, etc.) without modifying the
socket itself.
The socket is closed for modification (its design doesn’t change) but open for extension (you can
add different devices).
Definition: Software entities (classes, modules, functions, etc.) should be open for extension but
closed for modification.
Example: Drawing shapes where we can add new shapes without changing existing code.
Example: Drawing shapes where we can add new shapes without changing existing
code.
*/
// Abstract shape
abstract class Shape {
abstract void draw();
}
// Circle shape
class Circle extends Shape {
void draw() {
System.out.println("Drawing Circle");
}
}
// Rectangle shape
class Rectangle extends Shape {
void draw() {
System.out.println("Drawing Rectangle");
}
}
// Drawing class
class Drawing {
private List<Shape> shapes = new ArrayList<>();
Superclass: Vehicle
Subclasses: Car, Bike, Bus
You can substitute any specific type of vehicle for another. If you replace a car with a bike in a
scenario where both are supposed to provide transportation, the system (transportation) should
still work correctly. If a type of vehicle (like a toy car that doesn't move) doesn't fulfill the same role
as a vehicle, it violates the LSP.
Example: Managing a collection of birds where subclasses can replace the superclass.
In this case, Ostrich violates LSP because it can't fly, leading to an exception. To follow LSP,
*/
class Bird {
public void fly() {
System.out.println("Flying");
}
}
A kitchen blender and a vacuum cleaner both operate using electricity. However, they have
different interfaces: a blender might have buttons for speed settings and pulse, while a
vacuum cleaner might have settings for suction power.
If you were forced to use a common interface for all appliances, you would have to include
irrelevant methods for each device. By having separate, specific interfaces, each appliance only
uses the methods it needs.
interface Printer {
void print(Document document);
}
interface Scanner {
void scan(Document document);
}
class Document {}
Definition: 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.
Instead of the remote control being designed specifically for each device, it uses an abstract
interface like IR (infrared) or Bluetooth. Each device (TV, air conditioner, etc.) implements this
interface. The remote control does not need to know the details of each device; it just sends signals
via the abstract interface.
By using this abstraction, you can use the same remote control for different devices without
redesigning it for each specific one.
Definition: 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.
By using the Switchable interface, the ElectricSwitch class does not depend on the specific
implementations of devices, adhering to the Dependency Inversion Principle .
interface Switchable {
void turnOn();
void turnOff();
}
class ElectricSwitch {
private Switchable device;
Here's a very simple example in Java that follows the Single Responsibility Principle (SRP). This
principle states that a class should have only one reason to change, meaning it should have only
one job or responsibility.
Let's create a program that handles employee management, where we separate the responsibilities
of handling employee data and calculating their salary.
Employee.java
// Employee.java
public class Employee {
private String name;
private int hoursWorked;
private double hourlyRate;
SalaryCalculator.java
// SalaryCalculator.java
public class SalaryCalculator {
public double calculateSalary(Employee employee) {
return employee.getHoursWorked() * employee.getHourlyRate();
}
}
Main.java
// Main.java
public class Main {
public static void main(String[] args) {
Employee employee = new Employee("John Doe", 40, 20.0);
SalaryCalculator salaryCalculator = new SalaryCalculator();
double salary = salaryCalculator.calculateSalary(employee);
System.out.println("Salary of " + employee.getName() + ": $" +
salary);
}
}
2.1 Explanation:
This way, each class has a single responsibility, making the code easier to understand and maintain.
javac *.java
java Main