Single Responsibility Principle (SRP) in Java

Writing Clean, Maintainable and Scalable Code
Software systems grow over time. As features increase, code can easily become complex and difficult to maintain. To prevent this, developers follow design principles that help structure code properly.
One of the most important principles in object-oriented design is the Single Responsibility Principle (SRP).
SRP is the first principle of the SOLID design principles and it focuses on keeping classes simple and focused.
What is the Single Responsibility Principle?
The Single Responsibility Principle states:
A class should have only one responsibility and one reason to change.
In simple terms:
A class should perform only one task
A class should focus on one specific functionality
If a class does multiple unrelated tasks, it violates SRP
This principle helps developers write clean, modular, and maintainable code.
Understanding the Problem Without SRP
Imagine we are building a User Registration System.
When a user registers, the system should:
Register the user
Save the user in the database
Send a welcome email
A beginner developer might write something like this:
class UserService {
public void registerUser(String username) {
System.out.println("Registering user: " + username);
}
public void saveUserToDatabase(String username) {
System.out.println("Saving user to database: " + username);
}
public void sendWelcomeEmail(String username) {
System.out.println("Sending welcome email to: " + username);
}
}
At first glance, this looks fine. But this class is doing three different jobs.
Responsibilities inside this class
User registration
Database storage
Email service
This violates the Single Responsibility Principle.
Why is This a Problem?
If something changes in the system:
Scenario 1: Database changes
Maybe we move from MySQL to MongoDB.
Now we must modify this class.
Scenario 2: Email system changes
Maybe we integrate SendGrid or AWS SES.
Again, we must modify the same class.
Scenario 3: Registration logic changes
We again modify the same class.
So this class has multiple reasons to change, which breaks SRP.
Applying the Single Responsibility Principle
To fix this, we separate responsibilities into different classes.
Each class should focus on only one job.
Step 1: User Registration Responsibility
class UserService {
public void registerUser(String username) {
System.out.println("User registered: " + username);
}
}
This class now only handles user registration.
Step 2: Database Responsibility
class UserRepository {
public void saveUser(String username) {
System.out.println("Saving user to database: " + username);
}
}
This class only handles database operations.
Step 3: Email Responsibility
class EmailService {
public void sendWelcomeEmail(String username) {
System.out.println("Sending welcome email to: " + username);
}
}
This class only handles email notifications.
Using These Classes Together
Now we can combine these classes in the application.
public class Main {
public static void main(String[] args) {
String username = "Booster";
UserService userService = new UserService();
UserRepository userRepository = new UserRepository();
EmailService emailService = new EmailService();
userService.registerUser(username);
userRepository.saveUser(username);
emailService.sendWelcomeEmail(username);
}
}
Each class now has a single responsibility, which follows SRP.
Program Flow After Applying SRP
Here is how the system works step by step.
User Registration Request
│
▼
UserService
(registerUser)
│
▼
UserRepository
(saveUser)
│
▼
EmailService
(sendWelcomeEmail)
Each class focuses on one responsibility only.
Benefits of the Single Responsibility Principle
1. Easier Maintenance
If the email service changes, we only modify EmailService.
No other classes are affected.
2. Better Readability
When another developer reads the code, it becomes clear:
UserService→ handles registrationUserRepository→ handles databaseEmailService→ handles emails
3. Improved Testability
Each class can be tested independently.
Example:
Test user registration
Test database storage
Test email sending
4. Better Scalability
If tomorrow we add:
SMS notifications
Push notifications
Logging services
We simply create new classes, without modifying existing ones.
Real World Analogy
Think about a restaurant system.
| Role | Responsibility |
|---|---|
| Chef | Cooking food |
| Waiter | Serving food |
| Cashier | Handling payments |
Each person has one responsibility.
If one person handled everything, the system would become inefficient and chaotic.
The same concept applies to software design.
How to Identify SRP Violations
Ask yourself this question:
What is the responsibility of this class?
If the answer contains "and", SRP is likely violated.
Example:
This class handles user registration and email notifications.
That means the class has two responsibilities.
Simple Rule to Remember
One Class
=
One Responsibility
Conclusion
The Single Responsibility Principle helps developers create clean, maintainable, and scalable applications.
By ensuring that every class has only one responsibility, we achieve:
Cleaner architecture
Easier maintenance
Better testing
More scalable software systems
SRP is a small concept, but applying it consistently can greatly improve the quality of your codebase.




