LLD
Machine Coding
Interview Course
Java โ€ข Interview Prep
๐Ÿ“ SOLID Principles/

Interface Segregation Principle (ISP)

Lesson 4 of 5

Interface Segregation Principle (ISP)


What is it? (The Analogy)

Imagine you go to a hardware store to buy a screwdriver. Just a simple screwdriver. But the store only sells one tool: a gigantic Swiss Army Mega-Tool 9000. It has a screwdriver, but it ALSO has a saw, a wrench, a bottle opener, a fish scaler, a magnifying glass, and a tiny pair of scissors. You just needed a screwdriver, but now you are carrying around this heavy, unwieldy monster. And every time the manufacturer updates the fish scaler, YOU have to get a new tool even though you never scale fish.

Now imagine a better hardware store that sells individual tools: a screwdriver, a wrench, a saw -- each one small, light, and perfect for its specific job. You grab the screwdriver, and you are done.

The Interface Segregation Principle says: No class should be forced to implement methods it does not use. Instead of one massive "do everything" interface, split it into smaller, focused interfaces. Give each class only the contract it actually needs.

Think of it like a restaurant menu. A good restaurant does not hand every customer the same 200-page menu that includes breakfast, lunch, dinner, catering, and the wine list. The breakfast customer gets the breakfast menu. The dinner customer gets the dinner menu. Everyone gets exactly what is relevant to them, nothing more.


Why do we need it?

Let us feel the pain. Imagine you are building a document management system, and someone designs this interface:

java
1// BAD EXAMPLE -- The "God Interface" that tries to do everything
2public interface SmartDevice {
3
4    // Printing capabilities
5    void print(Document doc);
6    void printDuplex(Document doc);
7
8    // Scanning capabilities
9    void scan(Document doc);
10    void scanToEmail(Document doc, String email);
11
12    // Fax capabilities (yes, fax still exists apparently)
13    void fax(Document doc, String phoneNumber);
14
15    // Copy capabilities
16    void copy(Document doc, int numCopies);
17
18    // Network capabilities
19    void connectToWifi(String networkName);
20
21    // Maintenance
22    void orderInk();
23    void runDiagnostics();
24}

Now let us try to implement a simple, basic printer:

java
1// This poor little printer just wants to print...
2public class BasicPrinter implements SmartDevice {
3
4    @Override
5    public void print(Document doc) {
6        System.out.println("Printing: " + doc.getTitle());
7        // This is what we are here for!
8    }
9
10    @Override
11    public void printDuplex(Document doc) {
12        System.out.println("Printing both sides: " + doc.getTitle());
13    }
14
15    // Ugh, we do not scan! But we MUST implement this...
16    @Override
17    public void scan(Document doc) {
18        throw new UnsupportedOperationException("Basic printer cannot scan!");
19    }
20
21    @Override
22    public void scanToEmail(Document doc, String email) {
23        throw new UnsupportedOperationException("Basic printer cannot scan!");
24    }
25
26    // We definitely do not fax!
27    @Override
28    public void fax(Document doc, String phoneNumber) {
29        throw new UnsupportedOperationException("Basic printer cannot fax!");
30    }
31
32    @Override
33    public void copy(Document doc, int numCopies) {
34        throw new UnsupportedOperationException("Basic printer cannot copy!");
35    }
36
37    @Override
38    public void connectToWifi(String networkName) {
39        throw new UnsupportedOperationException("Basic printer has no wifi!");
40    }
41
42    @Override
43    public void orderInk() {
44        System.out.println("Ordering ink cartridge...");
45    }
46
47    @Override
48    public void runDiagnostics() {
49        System.out.println("Running basic diagnostics...");
50    }
51}

The pain: Our simple BasicPrinter was forced to implement 7 methods it does not support. That is 7 methods that either throw exceptions, do nothing, or lie. Every class that implements SmartDevice must deal with ALL of this, even if it only needs a fraction. And notice how this also violates LSP -- you cannot safely substitute a BasicPrinter where the code expects scanning!


The Classic Violation -- The God Interface

The "God Interface" (also called the "fat interface") is the poster child of ISP violations. You will recognize it by these symptoms:

java
1// Classic God Interface symptoms:
2public interface IEverything {
3    // 20+ methods
4    // Multiple unrelated groups of behavior
5    // Most implementing classes throw UnsupportedOperationException
6    // Methods were added "just in case someone needs them"
7    // The interface name is vague: "Manager", "Handler", "Service", "Processor"
8}

Real-world examples of fat interfaces that cause pain:

  • A UserService interface with authentication, profile management, email, permissions, analytics, and notification methods -- all in one
  • A Repository interface that forces read-only views to implement save(), update(), and delete()
  • A Worker interface that makes office workers implement operateHeavyMachinery()

Warning: If you see throw new UnsupportedOperationException() scattered across your codebase, you almost certainly have an ISP violation. Those exceptions are the code screaming "I was forced to implement something I should not have!"


How to Fix It -- Step by Step

  1. Identify the groups -- Look at your fat interface and group methods by which classes actually use them. Methods that are always used together belong in the same interface.
  1. Split into focused interfaces -- Create one small interface per group. Each interface should represent a single capability or role.
  1. Name them by capability -- Use names like Printable, Scannable, Faxable -- names that describe what you CAN DO, not what you ARE.
  1. Let classes pick and choose -- Each class implements only the interfaces it genuinely supports. A basic printer implements Printable. A multifunction device implements Printable, Scannable, and Faxable.
  1. Depend on the smallest interface possible -- When writing a method that only needs to print, accept Printable, not SmartDevice. This keeps your code flexible and testable.

Let us Build It Together

Let us refactor our printer nightmare into a clean, ISP-compliant design. We will build an Office Equipment System step by step.

java
1// ========================================
2// Step 1: Split the God Interface into
3// small, focused interfaces
4// Each one represents ONE capability
5// ========================================
6
7// Can it print documents?
8public interface Printable {
9    void print(Document doc);
10    void printDuplex(Document doc);
11}
12
13// Can it scan documents?
14public interface Scannable {
15    void scan(Document doc);
16    void scanToEmail(Document doc, String email);
17}
18
19// Can it send faxes? (for the 3 companies that still use fax)
20public interface Faxable {
21    void fax(Document doc, String phoneNumber);
22}
23
24// Can it copy documents?
25public interface Copyable {
26    void copy(Document doc, int numCopies);
27}
28
29// Can it connect to a network?
30public interface NetworkConnectable {
31    void connectToWifi(String networkName);
32    boolean isConnected();
33}
34
35// Can it self-maintain?
36public interface SelfMaintainable {
37    void orderSupplies();
38    void runDiagnostics();
39}
java
1// ========================================
2// Step 2: Basic Printer -- only implements
3// what it ACTUALLY does. No faking!
4// ========================================
5public class BasicInkjetPrinter implements Printable, SelfMaintainable {
6
7    private String model;
8
9    public BasicInkjetPrinter(String model) {
10        this.model = model;
11    }
12
13    @Override
14    public void print(Document doc) {
15        System.out.println("[" + model + "] Printing: " + doc.getTitle());
16    }
17
18    @Override
19    public void printDuplex(Document doc) {
20        System.out.println("[" + model + "] Duplex printing: " + doc.getTitle());
21    }
22
23    @Override
24    public void orderSupplies() {
25        System.out.println("[" + model + "] Ordering new ink cartridge...");
26    }
27
28    @Override
29    public void runDiagnostics() {
30        System.out.println("[" + model + "] Running print head alignment...");
31    }
32
33    // Notice: NO scan, NO fax, NO copy, NO wifi methods!
34    // We only implement what we truly support!
35}
java
1// ========================================
2// Step 3: The fancy multifunction device
3// implements ALL capabilities it supports
4// ========================================
5public class OfficePro3000 implements Printable, Scannable, Faxable,
6                                       Copyable, NetworkConnectable,
7                                       SelfMaintainable {
8
9    private String model = "OfficePro 3000";
10    private boolean connected = false;
11
12    @Override
13    public void print(Document doc) {
14        System.out.println("[" + model + "] High-quality printing: " + doc.getTitle());
15    }
16
17    @Override
18    public void printDuplex(Document doc) {
19        System.out.println("[" + model + "] Fast duplex printing: " + doc.getTitle());
20    }
21
22    @Override
23    public void scan(Document doc) {
24        System.out.println("[" + model + "] Scanning at 600 DPI: " + doc.getTitle());
25    }
26
27    @Override
28    public void scanToEmail(Document doc, String email) {
29        System.out.println("[" + model + "] Scanning and emailing to " + email);
30    }
31
32    @Override
33    public void fax(Document doc, String phoneNumber) {
34        System.out.println("[" + model + "] Faxing to " + phoneNumber);
35    }
36
37    @Override
38    public void copy(Document doc, int numCopies) {
39        System.out.println("[" + model + "] Making " + numCopies + " copies of: " + doc.getTitle());
40    }
41
42    @Override
43    public void connectToWifi(String networkName) {
44        System.out.println("[" + model + "] Connected to WiFi: " + networkName);
45        connected = true;
46    }
47
48    @Override
49    public boolean isConnected() {
50        return connected;
51    }
52
53    @Override
54    public void orderSupplies() {
55        System.out.println("[" + model + "] Auto-ordering toner from cloud service...");
56    }
57
58    @Override
59    public void runDiagnostics() {
60        System.out.println("[" + model + "] Running full system diagnostics...");
61    }
62}
java
1// ========================================
2// Step 4: A simple scanner with no printing!
3// ========================================
4public class PortableScanner implements Scannable {
5
6    @Override
7    public void scan(Document doc) {
8        System.out.println("[PortableScanner] Quick scan: " + doc.getTitle());
9    }
10
11    @Override
12    public void scanToEmail(Document doc, String email) {
13        System.out.println("[PortableScanner] Scan and email to " + email);
14    }
15
16    // That is it! A scanner scans. Period.
17}
java
1// ========================================
2// Step 5: Office code depends on ONLY
3// the interface it needs -- nothing more
4// ========================================
5public class OfficeApp {
6
7    // This method only needs printing -- accepts ANYTHING printable
8    public static void printReport(Printable printer, Document report) {
9        System.out.println("\n--- Printing Report ---");
10        printer.print(report);
11    }
12
13    // This method only needs scanning -- accepts ANYTHING scannable
14    public static void digitizeDocument(Scannable scanner, Document doc) {
15        System.out.println("\n--- Digitizing Document ---");
16        scanner.scan(doc);
17    }
18
19    // This method needs scanning AND emailing -- use both interfaces
20    public static void scanAndEmail(Scannable scanner, Document doc, String email) {
21        System.out.println("\n--- Scan and Email ---");
22        scanner.scanToEmail(doc, email);
23    }
24
25    public static void main(String[] args) {
26        Document report = new Document("Q4 Sales Report");
27        Document contract = new Document("Client Contract");
28
29        BasicInkjetPrinter basicPrinter = new BasicInkjetPrinter("HP DeskJet");
30        OfficePro3000 multiFunctionDevice = new OfficePro3000();
31        PortableScanner scanner = new PortableScanner();
32
33        // Print with the basic printer -- works!
34        printReport(basicPrinter, report);
35
36        // Print with the multifunction device -- also works!
37        printReport(multiFunctionDevice, report);
38
39        // Scan with the portable scanner -- works!
40        digitizeDocument(scanner, contract);
41
42        // Scan with the multifunction device -- also works!
43        digitizeDocument(multiFunctionDevice, contract);
44
45        // You CANNOT call printReport(scanner, report) -- compile error!
46        // The scanner is not Printable, and the compiler knows it!
47    }
48}

Aha moment: Notice how printReport() accepts Printable, not OfficePro3000 or SmartDevice. This means ANY future device that can print will work here -- even devices we have not invented yet. And we never force anything to pretend it can do something it cannot.


Visual Mental Model

java
1  BEFORE (Fat Interface):                  AFTER (Segregated Interfaces):
2
3  +-------------------------+              +----------+  +----------+
4  |      SmartDevice        |              | Printable|  | Scannable|
5  |-------------------------|              +----------+  +----------+
6  | + print()               |              +----------+  +-----------+
7  | + printDuplex()         |              |  Faxable |  | Copyable  |
8  | + scan()                |              +----------+  +-----------+
9  | + scanToEmail()         |              +----------------+
10  | + fax()                 |              |NetworkConnectable|
11  | + copy()                |              +----------------+
12  | + connectToWifi()       |
13  | + orderInk()            |
14  | + runDiagnostics()      |
15  +-------------------------+
16       |           |                   BasicPrinter:        OfficePro3000:
17  +---------+ +---------+             [Printable]           [Printable]
18  | Basic   | | Office  |             [SelfMaintainable]    [Scannable]
19  | Printer | | Pro3000 |                                   [Faxable]
20  +---------+ +---------+             PortableScanner:      [Copyable]
21  7 methods    All good               [Scannable]           [NetworkConnectable]
22  throw                                                     [SelfMaintainable]
23  exceptions!
24              Every class implements ONLY what it supports!

Connection to SRP

ISP is like SRP for interfaces. Just as SRP says a class should have one reason to change, ISP says an interface should serve one role or capability. When you split a fat interface, you are essentially applying SRP at the interface level. The two principles reinforce each other:

  • SRP asks: "Does this class have only one reason to change?"
  • ISP asks: "Does this interface force classes to implement things they should not?"

Both aim to keep things focused, cohesive, and free of unnecessary baggage.


How This Connects to Design Patterns

ISP directly enables the Adapter Pattern. When you have small, focused interfaces, it is easy to write adapters that translate between them. A class that implements Printable can be adapted to work with a legacy printing system through a thin adapter -- you do not need to adapt 15 methods, just 2.

The Facade Pattern also benefits from ISP. A facade presents a simplified interface to a complex subsystem. If the subsystem is built on small interfaces, the facade can cherry-pick exactly which capabilities to expose, creating a clean and minimal surface for clients.


Common Mistakes and Gotchas

  • Going too granular -- Do not create an interface for every single method (ICanPrint, ICanPrintDuplex as separate interfaces). Group methods that are always used together. If you never call print() without also needing printDuplex(), they belong in one interface.
  • Interface explosion -- If you end up with 30 tiny interfaces, you have gone too far. Look for natural groupings. The sweet spot is 3-7 methods per interface.
  • Renaming without restructuring -- Splitting SmartDevice into SmartDevice1 and SmartDevice2 misses the point. Name interfaces by CAPABILITY: Printable, Scannable, Faxable.
  • Forgetting to update dependencies -- After splitting, make sure your methods accept the smallest interface they need. If a method only prints, change its parameter from SmartDevice to Printable.
  • Marker interfaces with no methods -- An interface with zero methods (just used as a "tag") is sometimes useful, but do not confuse it with ISP. ISP is about not forcing unnecessary method implementations.

Interview Tip

When you see a class with several methods that throw UnsupportedOperationException or have empty bodies, point it out immediately: "This looks like an ISP violation -- the interface is forcing this class to implement methods it does not support. I would split the interface into smaller, role-based interfaces." Then sketch the split on the whiteboard. This demonstrates that you understand interface design, not just class design. Bonus points: mention that ISP makes testing easier because you can mock a small interface instead of a giant one with 15 methods.


Quick Quiz

  1. You have a Vehicle interface with methods: drive(), fly(), sail(), and refuel(). A Car class implements this interface. What is wrong, and how would you fix it?
  1. Your team has an interface DataStore with methods: read(), write(), delete(), and backup(). A ReadOnlyCache class implements DataStore and throws exceptions for write(), delete(), and backup(). Redesign this.
  1. Is it possible to have TOO MANY small interfaces? When would splitting go too far?

Summary -- Key Takeaways

  • No class should be forced to implement methods it does not use. Fat interfaces create fake implementations, wasted code, and runtime errors.
  • Split big interfaces into small, role-based ones. Name them by capability: Printable, Scannable, Flyable. Classes then implement only what they truly support.
  • ISP is SRP for interfaces. Just as classes should have one reason to change, interfaces should serve one role.
  • Depend on the smallest interface you need. If a method only needs to print, accept Printable -- not the 15-method SmartDevice monolith. This keeps your code flexible, testable, and future-proof.