Skip to main content

Command Palette

Search for a command to run...

Single Responsibility Principle (SRP) in Java

Updated
5 min read
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:

  1. Register the user

  2. Save the user in the database

  3. 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 registration

  • UserRepository → handles database

  • EmailService → 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.


Design Principles for Java Developers

Part 5 of 10

This series explains core Java design principles and SOLID principles with simple examples, real-world use cases, and interview-focused explanations to help developers write clean, maintainable, and scalable code.

Up next

SLAP Principle in Java: Writing Cleaner and More Readable Code

Introduction When developers read code, they should be able to understand it quickly without confusion. However, many programs become difficult to read because high-level logic and low-level implement