Interface Segregation Principle in Java with Example

Introduction

The Interface Segregation Principle (ISP) is one of the five SOLID principles of object-oriented design. ISP states that no client should be forced to depend on methods they do not use. This principle promotes the creation of smaller, more specific interfaces instead of larger, general-purpose interfaces, ensuring that classes implement only the methods that are relevant to them.

Table of Contents

  1. What is the Interface Segregation Principle?
  2. Benefits of the Interface Segregation Principle
  3. Example: Violation of ISP
  4. Example: Adherence to ISP
  5. Real-World Example
  6. Conclusion

1. What is the Interface Segregation Principle?

The Interface Segregation Principle (ISP) asserts that clients should not be forced to depend on interfaces they do not use. In other words, an interface should not include methods that are not relevant to the implementing class. Instead, interfaces should be small and focused on specific sets of behaviors.

2. Benefits of the Interface Segregation Principle

  • Improved Maintainability: Smaller interfaces are easier to implement, maintain, and understand.
  • Enhanced Flexibility: Changes in one part of the system are less likely to affect other parts.
  • Increased Reusability: Classes can implement only the interfaces they need, promoting reuse.

3. Example: Violation of ISP

In this example, we'll create an interface Worker that violates ISP by including methods not relevant to all implementing classes.

Example:

interface Worker {
    void work();
    void eat();
}

class Developer implements Worker {
    @Override
    public void work() {
        System.out.println("Developer is coding.");
    }

    @Override
    public void eat() {
        System.out.println("Developer is eating.");
    }
}

class Robot implements Worker {
    @Override
    public void work() {
        System.out.println("Robot is working.");
    }

    @Override
    public void eat() {
        // Robot does not eat
        throw new UnsupportedOperationException("Robot does not eat.");
    }
}

public class Main {
    public static void main(String[] args) {
        Worker developer = new Developer();
        developer.work(); // Output: Developer is coding.
        developer.eat();  // Output: Developer is eating.

        Worker robot = new Robot();
        robot.work(); // Output: Robot is working.
        robot.eat();  // Throws UnsupportedOperationException
    }
}

Issues:

  • The Robot class is forced to implement the eat method, which is not applicable to it.
  • This leads to a violation of ISP as the Robot class depends on a method it does not use.

4. Example: Adherence to ISP

To adhere to ISP, we can split the Worker interface into more specific interfaces.

Example:

Step 1: Define Specific Interfaces

interface Workable {
    void work();
}

interface Eatable {
    void eat();
}

Step 2: Implement the Specific Interfaces

class Developer implements Workable, Eatable {
    @Override
    public void work() {
        System.out.println("Developer is coding.");
    }

    @Override
    public void eat() {
        System.out.println("Developer is eating.");
    }
}

class Robot implements Workable {
    @Override
    public void work() {
        System.out.println("Robot is working.");
    }
}

Step 3: Main Class to Demonstrate ISP

public class Main {
    public static void main(String[] args) {
        Workable developer = new Developer();
        developer.work(); // Output: Developer is coding.

        Eatable eatableDeveloper = (Eatable) developer;
        eatableDeveloper.eat(); // Output: Developer is eating.

        Workable robot = new Robot();
        robot.work(); // Output: Robot is working.
    }
}

Explanation:

  • Workable: An interface with the work method.
  • Eatable: An interface with the eat method.
  • Developer: A class that implements both Workable and Eatable interfaces.
  • Robot: A class that implements only the Workable interface.
  • Main: Demonstrates the use of ISP by allowing classes to implement only the methods they need.

5. Real-World Example

Example: Document Printing System

Consider a document printing system where different devices have different capabilities.

Step 1: Define Specific Interfaces

interface Printable {
    void print();
}

interface Scannable {
    void scan();
}

interface Faxable {
    void fax();
}

Step 2: Implement the Specific Interfaces

class Printer implements Printable {
    @Override
    public void print() {
        System.out.println("Printing document.");
    }
}

class Scanner implements Scannable {
    @Override
    public void scan() {
        System.out.println("Scanning document.");
    }
}

class AllInOnePrinter implements Printable, Scannable, Faxable {
    @Override
    public void print() {
        System.out.println("Printing document.");
    }

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

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

Step 3: Main Class to Demonstrate ISP

public class Main {
    public static void main(String[] args) {
        Printable printer = new Printer();
        printer.print(); // Output: Printing document.

        Scannable scanner = new Scanner();
        scanner.scan(); // Output: Scanning document.

        AllInOnePrinter allInOnePrinter = new AllInOnePrinter();
        allInOnePrinter.print(); // Output: Printing document.
        allInOnePrinter.scan();  // Output: Scanning document.
        allInOnePrinter.fax();   // Output: Faxing document.
    }
}

Explanation:

  • Printable, Scannable, Faxable: Interfaces with specific methods.
  • Printer: A class that implements the Printable interface.
  • Scanner: A class that implements the Scannable interface.
  • AllInOnePrinter: A class that implements Printable, Scannable, and Faxable interfaces.
  • Main: Demonstrates the use of ISP by allowing devices to implement only the capabilities they support.

6. Conclusion

The Interface Segregation Principle (ISP) is a fundamental concept in object-oriented design that promotes the creation of small, specific interfaces rather than large, general-purpose ones. By adhering to ISP, developers can create more flexible, maintainable, and reusable code. Understanding and applying ISP is essential for building robust and scalable Java applications.

Happy coding!

Comments