JB Header
Single Responsibility Principle with Example in Java
This article explains Single Responsibility Principle with Example in Java. What is Single Responsibility Principle Single Responsibility Principle is one of the five principles of SOLID Design Principles. Specifically, the S in SOLID stands for Single Responsibility Principle.

Single Responsibility Principle was defined by Robert C. Martin as -
    →A class should have only one reason to change.

Wikipedia and many write-ups on Single Responsibility Principle describe it as -
    → A class should have only one responsibility.

Both of these definitions actually mean the same. For this we have to understand what is meant by Responsibility in the context of Single Responsibility Principle -
    →A Responsibility is nothing but a reason to change.

Now, combining the two definitions of Single Responsibility Principle based on how we defined Responsibility we get the final definition as below - Definition of Single Responsibility Principle
A class should have a single responsibility, where a responsibility is nothing but a reason to change.
What the definition means - When we design our classes, we should take care that one class at the most is responsible for doing one task or functionality among the whole set of responsibilities that it has. And only when there is a change needed in that specific task or functionality should this class be changed.
Also note that the classes defined using the Single Responsibility Principle are inherently cohesive in nature, i.e. their structure - attributes & behavior - are specific to that single functionality only to which the class caters to.
Application of Single Responsibility Principle The definition of Single Responsibility Principle sounds simple i.e. one class has one responsibility. But in reality, designs go in the other direction. Lets see an example to understand. Take a look at the Employee class below -
Employee.java
public class Employee{
  private String employeeId;
  private String name;
  private string address; 
  private Date dateOfJoining;
  public boolean isPromotionDueThisYear(){
    //promotion logic implementation
  }
  public Double calcIncomeTaxForCurrentYear(){
    //income tax logic implementation
  }
  //Getters & Setters for all the private attributes
}
The above Employee class looks logically correct. It has all the employee attributes like employeeId, name, age, address & dateOfJoining. It even tells you if the employee is eligible for promotion this year and calculates the income tax he has to pay for the year.

However, Employee class breaks the Single Responsibility Principle. Lets see how -
  • The logic of determining whether the employee is due this year is actually not a responsibility which the employee owns. The company's HR department owns this responsibility based on the company's HR policies which may change every few years. On any such change in HR policies, the Employee class will need to be updated as it is currently has the responsibility of promotion determination.
  • Similarly, income tax calculation is not a responsibility of the Employee. It is the finance department's responsibility which it takes care of the current tax structure which may get updated every year. If Employee class owns the income tax calculation responsibility then whenever tax structure/calculations change Employee class will need to be changed.
  • Lastly, Employee class should have the single responsibility of maintaining core attributes of an employee.
Refactoring the Employee class so that it adheres to Single Responsibility Principle Let us now refactor the Employee class to make it own a single responsibility.

Lets move the promotion determination logic from Employee class to the HRPromotions class like this -
HRPromotions.java
public class HRPromotions{
  public boolean isPromotionDueThisYear(Employee emp){
    //promotion logic implementation using the employee information passed
  }
}
Similarly, lets move the income tax calculation logic from Employee class to FinITCalculations class -
FinITCalculations.java
public class FinITCalculations{
  public Double calcIncomeTaxForCurrentYear(Employee emp){
    //income tax logic implementation using the employee information passed
  }
}
Our Employee class now remains with a single responsibility of maintaining core employee attributes -
Employee.java adhering to Single Responsibility Principle
public class Employee{ 
  private String employeeId;
  private String name;
  private string address; 
  private Date dateOfJoining;
  //Getters & Setters for all the private attributes
}
I have summarized the above Single Responsibility Principle based refactoring in diagram below -
Single Responsibility Principle with Example in Java
Summary This tutorial explained what is Single Responsibility Principle, then used an example in Java to show how this principle should be adhered to.