Interface segregation principle#

ISP

tl;dr Make fine grained interfaces that are client specific. Clients should not be forced to depend on interfaces they do not use.

The Interface segregation principle (ISP) is a design principle that suggests clients should not be forced to depend on interfaces they don’t use. It emphasizes the idea of creating specific and focused interfaces rather than large, monolithic ones.

In simpler terms, the ISP states that it’s better to have multiple smaller interfaces that are tailored to specific needs, rather than having a single interface that tries to cover all possible behaviors. By doing so, we prevent clients from being burdened with unnecessary dependencies on methods they don’t require.

A bad example violating the ISP in Java:

Bad example - Violation of the ISP#
 interface Machine {
     void printDocument();
     void scanDocument();
     void faxDocument();
 }

 class AllInOneMachine implements Machine {
     public void printDocument() {
         // Implementation for printing
     }

     public void scanDocument() {
         // Implementation for scanning
     }

     public void faxDocument() {
         // Implementation for faxing
     }
 }

In this example, we have an Machine interface that defines three methods: printDocument(), scanDocument(), and faxDocument(). However, the AllInOneMachine class implementing this interface must provide implementations for all three methods, even though it might not use or need all of them.

To adhere to the Interface Segregation Principle, we can refactor the code by creating smaller, more focused interfaces. Here’s an updated version:

Adhering to ISP (Java)#
 interface Printer {
     void printDocument();
 }

 interface Scanner {
     void scanDocument();
 }

 interface FaxMachine {
     void faxDocument();
 }

 class OfficePrinter implements Printer {
     public void printDocument() {
         // Implementation for printing in an office setting
     }
 }

 class HomeScanner implements Scanner {
     public void scanDocument() {
         // Implementation for scanning at home
     }
 }

 class MultiFunctionalMachine implements Printer, Scanner, FaxMachine {
     public void printDocument() {
         // Implementation for printing
     }

     public void scanDocument() {
         // Implementation for scanning
     }

     public void faxDocument() {
         // Implementation for faxing
     }
 }

In this refactored code, we have created separate interfaces (Printer, Scanner, and FaxMachine) that represent specific behaviors. The classes can now implement the interfaces that they require, leading to more focused and modular code.

Clients can choose to implement one or more of these interfaces based on their requirements, avoiding unnecessary dependencies and providing a clearer contract for each behavior.

By adhering to the ISP, we ensure that clients only depend on the interfaces they need, leading to more modular, maintainable, and flexible code. It allows for better separation of concerns and promotes easier code reuse and extensibility.