Clients should not depend on methods they do not use.
A monolithic UserRepository interface forces every consumer to depend on methods they don't need.
Split into narrow, role-based interfaces.
// ─── EXAMPLE 1 ──────────────────────────────────────────────────────────────
// WHAT WE ARE IMPLEMENTING:
// A smart multifunction printer system where specialized machines implement
// only what they actually do.
//
// WHERE THE PRINCIPLE FITS IN:
// Split the monolithic Machine interface into highly cohesive interfaces:
// Printer, Scanner, and Fax. A basic printer implements only Printer,
// preventing unused methods.
// ────────────────────────────────────────────────────────────────────────────
import java.util.List;
// --- Bad: Fat interface ---
interface UserRepository {
User findById(String id);
void save(User user);
void delete(String id);
void update(User user);
List<User> findActiveUsers();
List<UserAudit> getAuditTrail(String userId);
AnalyticsReport getAnalytics(String query);
void exportToCSV();
}
// Every consumer depends on all methods, even if they only need one.
// --- Good: Segregated interfaces ---
interface UserReader {
User findById(String id);
List<User> findActiveUsers();
}
interface UserWriter {
void save(User user);
void update(User user);
void delete(String id);
}
interface UserAuditReader {
List<UserAudit> getAuditTrail(String userId);
}
interface UserAnalyticsReader {
AnalyticsReport getAnalytics(String query);
}
// --- Concrete implementation ---
class PostgresUserRepository implements UserReader, UserWriter, UserAuditReader, UserAnalyticsReader {
public User findById(String id) {
System.out.println(" [DB] SELECT * FROM users WHERE id = " + id);
return new User(id, "alice");
}
public void save(User user) { System.out.println(" [DB] INSERT INTO users ..."); }
public void update(User user) { System.out.println(" [DB] UPDATE users ..."); }
public void delete(String id) { System.out.println(" [DB] DELETE FROM users ..."); }
public List<User> findActiveUsers() { return List.of(new User("1", "alice"), new User("2", "bob")); }
public List<UserAudit> getAuditTrail(String userId) {
return List.of(new UserAudit(userId, "LOGIN", 1000L));
}
public AnalyticsReport getAnalytics(String query) { return new AnalyticsReport("results"); }
}
// --- Clients depend only on what they need ---
class UserAuthService {
private final UserReader reader;
public UserAuthService(UserReader reader) { this.reader = reader; }
public User authenticate(String id) { return reader.findById(id); }
}
class UserRegistrationService {
private final UserWriter writer;
public UserRegistrationService(UserWriter writer) { this.writer = writer; }
public void register(User user) { writer.save(user); }
}
class UserAdminService {
private final UserAuditReader auditReader;
public UserAdminService(UserAuditReader auditReader) { this.auditReader = auditReader; }
public void showAudit(String userId) {
auditReader.getAuditTrail(userId).forEach(a -> System.out.println(" Audit: " + a));
}
}
// Utility classes for demo
record User(String id, String name) {}
record UserAudit(String userId, String action, long timestamp) {}
record AnalyticsReport(String data) {}
public class Main {
public static void main(String[] args) {
PostgresUserRepository repo = new PostgresUserRepository();
UserAuthService auth = new UserAuthService(repo);
auth.authenticate("42");
UserRegistrationService reg = new UserRegistrationService(repo);
reg.register(new User("99", "bob"));
UserAdminService admin = new UserAdminService(repo);
admin.showAudit("42");
}
}