You are currently viewing Interface Segregation Principle In Java

Interface Segregation Principle In Java

Introduction

The Interface Segregation Principle (ISP) is the “I” in SOLID — and it helps you write clean, modular, and maintainable code.

Definition: No client should be forced to depend on methods it does not use.

In other words, interfaces should be small and focused. If an interface grows too large, different clients end up implementing methods that are irrelevant to them — breaking cohesion and adding unnecessary complexity.


1. Recognizing a Violation

Imagine we define a single interface for all types of machines:

interface Machine {
    void print();
    void scan();
    void fax();
}

Now we try to implement this for a simple printer:

class BasicPrinter implements Machine {
    public void print() {
        System.out.println("Printing...");
    }

    public void scan() {
        throw new UnsupportedOperationException();
    }

    public void fax() {
        throw new UnsupportedOperationException();
    }
}

This is a clear violation of ISP. BasicPrinter shouldn’t need to care about scanning or faxing.


2. Applying Interface Segregation

We break the large interface into smaller, role-specific ones:

interface Printer {
    void print();
}

interface Scanner {
    void scan();
}

interface Fax {
    void fax();
}

Now clients only implement what they need:

class BasicPrinter implements Printer {
    public void print() {
        System.out.println("Printing...");
    }
}

class AllInOneMachine implements Printer, Scanner, Fax {
    public void print() {
        System.out.println("Printing...");
    }

    public void scan() {
        System.out.println("Scanning...");
    }

    public void fax() {
        System.out.println("Faxing...");
    }
}

3. Real-World Example: File System Operations

Suppose you’re designing an interface to represent file operations:

interface FileManager {
    void read(String path);
    void write(String path, String content);
    void delete(String path);
}

Now, imagine you’re building a LogViewer component that only needs to read log files. You’re forced to implement irrelevant write() and delete() methods, possibly throwing exceptions or leaving them empty — a clear violation of ISP.


✅ Refactor with focused interfaces

interface ReadableFile {
    void read(String path);
}

interface WritableFile {
    void write(String path, String content);
}

interface DeletableFile {
    void delete(String path);
}

Now each client only depends on the methods it actually needs.

class LogViewer implements ReadableFile {
    public void read(String path) {
        System.out.println("Reading log file: " + path);
    }
}

class ConfigManager implements ReadableFile, WritableFile {
    public void read(String path) {
        System.out.println("Reading config: " + path);
    }

    public void write(String path, String content) {
        System.out.println("Writing config to: " + path);
    }
}

This design honors the Interface Segregation Principle by promoting clear and minimal responsibilities per class.

4. Benefits of Interface Segregation

  • Cleaner abstractions for clients
  • Better unit test isolation
  • Higher cohesion and lower coupling
  • More flexible code reuse

Conclusion

The Interface Segregation Principle prevents bloated abstractions that don’t reflect real responsibilities. By keeping interfaces focused, you ensure your Java code remains clean, modular, and easy to evolve.

You can find the complete code of this article here in GitHub.

📚 Related: Dependency Inversion Principle in Java

Noel Kamphoa

Experienced software engineer with expertise in Telecom, Payroll, and Banking. Now Senior Software Engineer at Societe Generale Paris.