Definition:
A class should have only one responsibility.
class UserService {
void addUser(String name) {
System.out.println("User added: " + name);
}
void sendEmail(String name) {
System.out.println("Email sent to: " + name);
}
}class UserService {
void addUser(String name) {
System.out.println("User added: " + name);
}
}
class EmailService {
void sendEmail(String name) {
System.out.println("Email sent to: " + name);
}
}Definition: Classes should be open for extension but closed for modification.
class DiscountCalculator {
double calculateDiscount(String type) {
if (type.equals("STUDENT")) {
return 10;
} else if (type.equals("SENIOR")) {
return 20;
}
return 0;
}
}interface Discount {
double apply();
}
class StudentDiscount implements Discount {
public double apply() {
return 10;
}
}
class SeniorDiscount implements Discount {
public double apply() {
return 20;
}
}Definition: Objects of a superclass should be replaceable with objects of its subclasses without breaking the expected behavior.
class Vehicle {
boolean hasEngine() {
return true;
}
}
class Motorcycle extends Vehicle {
// Motorcycles have engines ✔
}
class Bicycle extends Vehicle {
boolean hasEngine() {
throw new UnsupportedOperationException("Bicycle has no engine");
}
}
❌ Why this violates LSP
Vehicle promises that hasEngine() works
Bicycle breaks that contract
Code using Vehicle will crash when replaced with Bicycle
Example of breakage:
Vehicle vehicle = new Bicycle();
vehicle.hasEngine(); // 💥 Runtime exceptioninterface Vehicle {
}
interface EngineVehicle extends Vehicle {
boolean hasEngine();
}
class Motorcycle implements EngineVehicle {
public boolean hasEngine() {
return true;
}
}
class Bicycle implements Vehicle {
// No engine-related behavior
}Definition: A class should not be forced to implement methods it does not use.
interface Worker {
void work();
void eat();
}
class HumanWorker implements Worker {
public void work() {
System.out.println("Human working");
}
public void eat() {
System.out.println("Human eating");
}
}
class RobotWorker implements Worker {
public void work() {
System.out.println("Robot working");
}
public void eat() {
// ❌ Robots don’t eat
throw new UnsupportedOperationException("Robots do not eat");
}
}interface Workable {
void work();
}
interface Eatable {
void eat();
}
class HumanWorker implements Workable, Eatable {
public void work() {
System.out.println("Human working");
}
public void eat() {
System.out.println("Human eating");
}
}
class RobotWorker implements Workable {
public void work() {
System.out.println("Robot working");
}
}Definition: Classes should depend on interfaces not on concrete classes.
class MessageService {
void send() {
System.out.println("Sending message");
}
}
class Notification {
private MessageService messageService = new MessageService();
void notifyUser() {
messageService.send();
}
}interface MessageService {
void send();
}
class EmailService implements MessageService {
public void send() {
System.out.println("Sending email");
}
}
class Notification {
private MessageService messageService;
Notification(MessageService messageService) {
this.messageService = messageService;
}
void notifyUser() {
messageService.send();
}
}