Education Logo Images
Blog
Education Logo Images

Batchmate is an online coding platform offering free resources to help learners at all levels build and advance their coding skills.

  • batchmate.info@gmail.com
  • Blog
Find With Us
  • Home
  • Blogs
  • Details

SOLID Principles Using Java

Master the SOLID principles to design robust, maintainable, and scalable software. Learn to create clean code by ensuring single responsibility, extensibility, substitutability, focused interfaces, and dependency management.

  • Last updated: 03 Jun, 2025

The SOLID principles are a set of five design principles that guide object-oriented programming and design. They help developers create systems that are easy to maintain, scale, and extend. These principles are particularly useful for writing clean and maintainable code in Java. It was Conceptualized by Robert C. Martin, also known as Uncle Bob. Five Design principles of SOLID principles,



Single Responsibility Principle (SRP):

A class should have only one reason to change, meaning it should perform a single responsibility or task.

Example, Without SRP,

public class UserManager {
    public void addUser(User user) {
        // Add user logic
    }
    public void validateUser(User user) {
        // Validate user logic
    }
    public void sendWelcomeEmail(User user) {
        // Email sending logic
    }
}

With SRP,

public class UserManager {
    public void addUser(User user) {
        // Add user logic
    }
}
public class UserValidator {
    public void validateUser(User user) {
        // Validation logic
    }
}
public class EmailService {
    public void sendWelcomeEmail(User user) {
        // Email sending logic
    }
}

Here, the UserManager, UserValidator, and EmailService each have a single responsibility.

Open/Closed Principle (OCP):

Software entities (classes, modules, functions) should be open for extension but closed for modification.

Without OCP,

public class PaymentService {
    public void processPayment(String paymentType) {
        if (paymentType.equals("CREDIT_CARD")) {
            // Credit card processing
        } else if (paymentType.equals("PAYPAL")) {
            // PayPal processing
        }
    }
}

With OCP,

public interface PaymentProcessor {
    void processPayment();
}


public class CreditCardProcessor implements PaymentProcessor {
    @Override
    public void processPayment() {
        // Credit card processing
    }
}


public class PayPalProcessor implements PaymentProcessor {
    @Override
    public void processPayment() {
        // PayPal processing
    }
}


public class PaymentService {
    private final List processors;


    public PaymentService(List processors) {
        this.processors = processors;
    }


    public void processPayments() {
        for (PaymentProcessor processor : processors) {
            processor.processPayment();
        }
    }
}

New payment types can be added without modifying PaymentService.

Liskov Substitution Principle (LSP):

Subtypes must be substitutable for their base types without altering the correctness of the program.

Without LSP,

public class Rectangle {
    private int width;
    private int height;


    public void setWidth(int width) {
        this.width = width;
    }


    public void setHeight(int height) {
        this.height = height;
    }


    public int getArea() {
        return width * height;
    }
}


public class Square extends Rectangle {
    @Override
    public void setWidth(int width) {
        super.setWidth(width);
        super.setHeight(width);
    }


    @Override
    public void setHeight(int height) {
        super.setWidth(height);
        super.setHeight(height);
    }
}

With LSP,

public interface Shape {
    int getArea();
}


public class Rectangle implements Shape {
    private int width;
    private int height;


    public Rectangle(int width, int height) {
        this.width = width;
        this.height = height;
    }


    @Override
    public int getArea() {
        return width * height;
    }
}


public class Square implements Shape {
    private int side;


    public Square(int side) {
        this.side = side;
    }


    @Override
    public int getArea() {
        return side * side;
    }
}

Here, Square and Rectangle both implement Shape without breaking substitutability.

Interface Segregation Principle (ISP):

Clients should not be forced to implement interfaces they do not use.

Without ISP,

public interface Vehicle {
    void startEngine();
    void fly();
}


public class Car implements Vehicle {
    @Override
    public void startEngine() {
        // Start engine
    }


    @Override
    public void fly() {
        throw new UnsupportedOperationException("Cars can't fly");
    }
}

With ISP,

public interface EngineVehicle {
    void startEngine();
}


public interface FlyingVehicle {
    void fly();
}


public class Car implements EngineVehicle {
    @Override
    public void startEngine() {
        // Start engine
    }
}


public class Airplane implements EngineVehicle, FlyingVehicle {
    @Override
    public void startEngine() {
        // Start engine
    }


    @Override
    public void fly() {
        // Fly logic
    }
}

Dependency Inversion Principle (DIP):

High-level modules should not depend on low-level modules; both should depend on abstractions.

Without DIP,

public class UserRepository {
    public void save(User user) {
        // Save logic
    }
}
public class UserService {
    private final UserRepository userRepository = new UserRepository();
    public void saveUser(User user) {
        userRepository.save(user);
    }
}

With DIP,

public interface UserRepository {
    void save(User user);
}


public class JpaUserRepository implements UserRepository {
    @Override
    public void save(User user) {
        // Save logic
    }
}


public class UserService {
    private final UserRepository userRepository;


    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }
    public void saveUser(User user) {
        userRepository.save(user);
    }
}

By depending on UserRepository, the UserService can work with any repository implementation.

By following these SOLID principles, you ensure your Java code is modular, reusable, and easier to maintain.

SOLID Principles
Related Post

Similar Post

Card image
SOLID Principles Using PHP
  • 04 Jun, 2025
  • 3 min read

Master SOLID principles to build resilient, scalable software with maintainable, extensible, and decoupled code that is easier to test and evolve.

Learn More
Card image
SOLID Principles Using Java
  • 04 Jun, 2025
  • 3 min read

Master the SOLID principles to design robust, maintainable, and scalable software. Learn to create clean code by ensuring single responsibility, extensibility, substitutability, focused interfaces, and dependency management.

Learn More

Edu-cause

We’re here to support you in achieving your dream career!

Useful Links
  • Home
  • Terms and Conditions
  • Privacy Policy
Our Company
  • Faq
  • Blog
  • Contact Us
Get Contact
  • E-mail: batchmate.info@gmail.com

Copyright © 2024 Batchmate. All Rights Reserved