Interface segregation principle in Java
| Reading Time : 4 minutes | #backenddevelopment #Java
Interfaces play an important role in Java programming language and they are widely used for abstraction and to support multiple inheritances.
Interface is achieved by using a keyword interface and declare methods in it. Classes can implement interfaces with the implements keyword, and then provide implementations for the declared methods. One of the design principles to keep in mind while writing interfaces is the Interface Segregation Principle.
In Interface Segregation Principle interface should not have methods that implementing classes don’t require. Implementing classes are for no reason forced to provide implementations for those methods it does not require to. An addition of a method or change to a method signature to interface requires changing all classes implemented in this interface.
The Interface Segregation Principle suggests segregating an interface into smaller and highly cohesive interfaces, known as “role interfaces” and each “role interface” declares one or more methods for specific behavior. Thus clients, instead of implementing an interface implements only those “role interfaces” whose methods are relevant.
Consider the requirements of an application that builds different types of transportation vehicles. Each vehicle will have a price and color. Vehicles such as car can start and stop moving while some vehicles such as airplanes can both move and fly. Example interface
public interface Vehicle {
void setPrice(double price);
void setColor(String color);
void start();
void stop();
void fly();
}
A class that represents an aeroplane can implement the Vehicle interface and provide implementations of all the interface methods. But, imagine a class that represents a car. This is how the Car class will look.
public class Car implements Vehicle {
double price;
String color;
@Override
public void setPrice(double price) {
this.price = price;
}
@Override
public void setColor(String color) {
this.color=color;
}
@Override
public void start(){}
@Override
public void stop(){}
@Override
public void fly(){}
}
As you can see in the code, Car needs to provide an implementation fly() method, even though it does not require them. This is a violation of the Interface Segregation Principle. These might affect code readability
Following the Interface Segregation Principle, we can address the problem of the vehicle interface, solution is- Segregate the Vehicle interface into multiple role interfaces each for specific behavior. In this case, Vehicle interface can be broken down into three interfaces: Toy, Movable, and Flyable.
public interface Vehicle {
void setPrice(double price);
void setColor(String color);
}
public interface Movable {
void start();
void stop();
}
public interface Flyable {
void fly();
}
Now Vehicle interface with the setPrice() and setColor() methods as all vehicles will have a price and color, all Vehicle implementation classes can implement this interface. Then, Movable and Flyable interfaces to represent moving and flying behaviors in vehicles.
public class Car implements Vehicle, Movable {
double price;
String color;
@Override
public void setPrice(double price) {
this.price = price;
}
@Override
public void setColor(String color) {
this.color=color;
}
@Override
public void start(){
// Implementation
}
@Override
public void stop(){
// Implementation
}
}
public class Aeroplane implements Vehicle, Movable, Flyable {
double price;
String color;
@Override
public void setPrice(double price) {
this.price = price;
}
@Override
public void setColor(String color) {
this.color=color;
}
@Override
public void start(){
// Implementation
}
@Override
public void stop(){
// Implementation
}
@Override
public void fly(){
// Implementation
}
}
Now implementation classes implement those interfaces they are interested in and this helps to remove unnecessary code and is more readable
Next, let’s write a class to create objects of the implementation classes.
public class VehicleBuilder {
public static Car buildCar(){
ToyHouse toyHouse=new ToyHouse();
Car car = new Car();
car.setPrice(15.00);
car.setColor("green");
car.start();
return car;
}
public static Aeroplane buildAeroPlane(){
Aeroplane aeroplane = new Aeroplane();
aeroplane.setPrice(25.00);
aeroplane.setColor("red");
aeroplane.start();
aeroplane.fly();
return aeroplane;
}
}
Interface Segregation Principle ensures small, focused, and highly cohesive software components. Interface Segregation Principle is easy to understand and simple to follow. But, identifying the distinct interfaces can be challenging to get the right role segregation. The Interface Segregation Principle a very powerful concept to master when developing Java applications.
If you have liked this concept and understood this story you might like Command Patterns which I wrote in the past another behavioral design pattern and is part of the GoF‘s formal list of design patterns. This pattern intends to encapsulate in an object all the data required for performing a given action (command)
powerctl is a little weekend project I put together to provide a simple tool for managing power states on Linux. I had previously put my laptop into suspend with a basic “echo mem | doas tee /sys/power/state”, but this leaves a lot to be desired. I have to u…
via Drew DeVault's blog August 28, 2022Links to exhibits from the Microsoft anti-trust case, with a bit of info on each link. Projection of PC marketshare Share of new browser users Share of the browser market, grouped by major ISP, 3 month moving average Share of the browser market, grouped by ma…
via danluu.com August 24, 2022Hi all! This month I’ve been pondering offline-first apps. The online aspect of modern apps is an important feature for many use-cases: it enables collaboration between multiple people and seamless transition between devices (e.g. I often switch between my pe…
via emersion August 14, 2022Generated by openring