Interface Segregation
Definition

Violation Example
// BAD: Fat interface - forces unnecessary implementations
public interface Worker {
void work();
void eat();
void sleep();
void attendMeeting();
void writeReport();
void reviewCode();
}
// Human worker - uses all methods
public class Developer implements Worker {
public void work() { /* coding */ }
public void eat() { /* lunch break */ }
public void sleep() { /* rest */ }
public void attendMeeting() { /* standup */ }
public void writeReport() { /* status update */ }
public void reviewCode() { /* PR review */ }
}
// Robot worker - forced to implement irrelevant methods!
public class RobotWorker implements Worker {
public void work() { /* performs task */ }
public void eat() {
throw new UnsupportedOperationException(); // Robots don't eat!
}
public void sleep() {
throw new UnsupportedOperationException(); // Robots don't sleep!
}
public void attendMeeting() {
throw new UnsupportedOperationException();
}
public void writeReport() { /* can generate report */ }
public void reviewCode() {
throw new UnsupportedOperationException();
}
}
// Problems:
// - RobotWorker has meaningless methods
// - Client code might call inapplicable methods
// - Changes to eat() affect RobotWorker unnecessarily
Proper Implementation
// GOOD: Segregated interfaces
// Core work interface
public interface Workable {
void work();
}
// Human-specific needs
public interface Feedable {
void eat();
}
public interface Restable {
void sleep();
}
// Role-specific behaviors
public interface MeetingAttendee {
void attendMeeting();
}
public interface ReportWriter {
void writeReport();
}
public interface CodeReviewer {
void reviewCode();
}
// Developer implements only what they need
public class Developer implements Workable, Feedable, Restable,
MeetingAttendee, ReportWriter, CodeReviewer {
public void work() { /* coding */ }
public void eat() { /* lunch */ }
public void sleep() { /* rest */ }
public void attendMeeting() { /* standup */ }
public void writeReport() { /* status */ }
public void reviewCode() { /* PR review */ }
}
// Robot only implements applicable interfaces
public class RobotWorker implements Workable, ReportWriter {
public void work() { /* performs task */ }
public void writeReport() { /* generates report */ }
}
// Client code depends only on what it needs
public class TaskScheduler {
public void assignWork(Workable worker) {
worker.work(); // Works with any worker
}
}
public class LunchOrganizer {
public void scheduleLunch(Feedable person) {
person.eat(); // Only accepts those who eat
}
}
Real-World Example
// BAD: Repository with too many methods
public interface Repository<T> {
T findById(Long id);
List<T> findAll();
T save(T entity);
void delete(T entity);
void deleteById(Long id);
List<T> findByField(String field, Object value);
Page<T> findAll(Pageable pageable);
long count();
boolean existsById(Long id);
List<T> saveAll(List<T> entities);
void deleteAll();
// ... 20 more methods
}
// Some services only need to read
public class ReportService {
private Repository<Order> repo; // Has delete access it shouldn't!
}
// GOOD: Segregated repositories
public interface ReadRepository<T> {
Optional<T> findById(Long id);
List<T> findAll();
boolean existsById(Long id);
long count();
}
public interface WriteRepository<T> {
T save(T entity);
List<T> saveAll(List<T> entities);
}
public interface DeleteRepository<T> {
void delete(T entity);
void deleteById(Long id);
void deleteAll();
}
// Combine as needed
public interface CrudRepository<T> extends
ReadRepository<T>, WriteRepository<T>, DeleteRepository<T> {
}
// Services depend on minimal interface
public class ReportService {
private ReadRepository<Order> repo; // Can only read
}
public class OrderService {
private CrudRepository<Order> repo; // Full access
}
Interface Composition

Signs of ISP Violation

Applying ISP

Tips & Tricks
