Applying SOLID Principles in Java: Examples and Best Practices

Single Responsibility Principle (SRP)

This principle states that each class should have a single responsibility. It emphasizes that a class should perform one specific function and not have too many reasons to change.

Example: Managing user information and sending email notifications.

class UserManager {
  void createUser(UserData userData) {
    // Logic for creating a user
  }
}

class EmailService {
  void sendEmail(EmailData emailData) {
    // Logic for sending an email
  }
}

Open/Closed Principle (OCP)

This principle encourages extending functionality by adding new code rather than modifying existing code.

Example: Handling different payment methods in an e-commerce application.

abstract class PaymentProcessor {
  abstract void processPayment();
}

class CreditCardPaymentProcessor extends PaymentProcessor {
  void processPayment() {
    // Logic for processing credit card payment
  }
}

class PayPalPaymentProcessor extends PaymentProcessor {
  void processPayment() {
    // Logic for processing PayPal payment
  }
}

Liskov Substitution Principle (LSP)

This principle asserts that objects of a derived class should be substitutable for objects of the base class without affecting the correctness of the program.

Example: Managing geometric shapes.

abstract class Shape {
  abstract double area();
}

class Rectangle extends Shape {
  double area() {
    // Logic for calculating area of rectangle
  }
}

class Square extends Shape {
  double area() {
    // Logic for calculating area of square
  }
}

Interface Segregation Principle (ISP)

This principle advises breaking interfaces into smaller ones to avoid forcing classes to implement methods they don't need.

Example: Interfaces for updating and displaying data.

interface UpdateableFeature {
  void updateFeature();
}

interface DisplayableFeature {
  void displayFeature();
}

Dependency Inversion Principle (DIP)

This principle suggests using dependency injection to manage dependencies.

Example: Using dependency injection to manage dependencies.

class OrderProcessor {
  private final DBConnection dbConnection;
  private final EmailService emailService;

  OrderProcessor(DBConnection dbConnection, EmailService emailService) {
    this.dbConnection = dbConnection;
    this.emailService = emailService;
  }
}

Remember that applying SOLID principles in Java should be done flexibly based on the specific purpose of your project and your understanding of SOLID and Java.