Interface Segregation Principle

Interface Segregation Principle is fourth principle from SOLID acronym and the definition is: Clients should not be forced to depend upon interfaces that they do not use. It means that we should be very careful while creating interfaces and make sure that classes that would be implementing these interfaces will not be forced to override methods that they do not need. This principle is similar to Liskov principle but this time we are looking on design from different perspective, our focus is not on making classes replaceable but on rethinking initial design and abstractions.

In real-life following example comes to my mind. In my town there is very good pizzeria but they have one thing that I cannot stand. Namely, they add arugula to all kinds of pizza from their menu. You order Diavola you get arugula, you order Napoli they add arugula as well. Let’s see this example from code perspective. First let’s create interface called PizzaBase with four methods makePizzaDough, addCheese, addTomatoSauce and addArugula.

public interface PizzaBase {
void makePizzaDough();
void addCheese();
void addTomatoSauce();
void addArugula();
}

Then we have two classes that implement this interface, Napoli and Diavola.

public class Napoli implements PizzaBase {
public void makePizzaDough() {
System.out.println("Make pizza dough.");
}
public void addCheese() {
System.out.println("Add cheese.");
}
public void addTomatoSauce() {
System.out.println("Add tomato sauce.");
}
public void addArugula() {
System.out.println("Add arugula.");
}
public void addParmaHam() {
System.out.println("Add Parma ham.");
}
}
public class Diavola implements PizzaBase {
public void makePizzaDough() {
System.out.println("Make pizza dough.");
}
public void addCheese() {
System.out.println("Add cheese.");
}
public void addTomatoSauce() {
System.out.println("Add tomato sauce.");
}
public void addArugula() {
System.out.println("Add arugula.");
}
public void addBacon() {
System.out.println("Add bacon.");
}
}

Let’s look at UML diagram to get everything right.

UML diagram

From my perspective which is the perspective of a client of this pizzeria, I do not want to have addArugula method in my Diavola class but because of wrong design of interface I need to implement this method. The solution of this problem could be separation of PizzaBase interface into two interfaces. First of them would be the same interface but without addArugula method and the second one would be interface named for example Arugula with only one method which would be addArugula. But the best solution is to separate PizzaBase interface into four different interfaces with only one method for all of them. Why? Because in the future for example we would like to add new dish to our pizzeria, like hamburger or cheeseburger. Let’s see our new code. First our four new interfaces, PizzaDough, Cheese, TomatoSauce and Arugula.

public interface PizzaDough {
void makePizzaDough();
}
public interface Cheese {
void addCheese();
}
public interface TomatoSauce {
void addTomatoSauce();
}
public interface Arugula {
void addArugula();
}

And our two classes, Napoli and Diavola.

public class Napoli implements PizzaDough, Cheese, TomatoSauce, Arugula {
public void makePizzaDough() {
System.out.println("Make pizza dough.");
}
public void addCheese() {
System.out.println("Add cheese.");
}
public void addTomatoSauce() {
System.out.println("Add tomato sauce.");
}
public void addArugula() {
System.out.println("Add arugula.");
}
public void addParmaHam() {
System.out.println("Add Parma ham.");
}
}
public class Diavola implements PizzaDough, Cheese, TomatoSauce {
public void makePizzaDough() {
System.out.println("Make pizza dough.");
}
public void addCheese() {
System.out.println("Add cheese.");
}
public void addTomatoSauce() {
System.out.println("Add tomato sauce.");
}
public void addBacon() {
System.out.println("Add bacon.");
}
}

Let’s also add new class, Cheeseburger.

public class Cheeseburger implements Cheese, TomatoSauce {
public void addCheese() {
System.out.println("Add cheese.");
}
public void addTomatoSauce() {
System.out.println("Add tomato sauce.");
}
public void addBurger() {
System.out.println("Add burger.");
}
}

That’s more like it. Let’s see this on UML diagram.

UML diagram

To sum up, the main advantages of this principle is that classes do not need to implement methods that they do not use and properties or methods which do not fit together are split into different interfaces.

Leave a Comment

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *

Scroll to Top