Skip to main content

Practice Problems for Single Responsibility

Single Responsibility Principle (SRP)

Practice Problems

To master the Single Responsibility Principle, it's essential to engage in practical exercises and projects. Here are some complete coding exercises, sample projects, and quizzes to help reinforce your understanding.

Coding Exercises

  • Exercise 1: Refactor a Monolithic Class:

    Given:

public class UserService {
public boolean authenticateUser(String username, String password) {
// Authentication logic
}

public UserData getUserData(String userId) {
// Data retrieval logic
}

public void logActivity(String userId, String activity) {
// Logging logic
}
}

Refactored:

public class AuthenticationService {
public boolean authenticateUser(String username, String password) {
// Authentication logic
}
}

public class UserDataService {
public UserData getUserData(String userId) {
// Data retrieval logic
}
}

public class ActivityLogService {
public void logActivity(String userId, String activity) {
// Logging logic
}
}
  • Exercise 2: Implement a Facade Pattern:

    Given:

public class OrderProcessing {
public void processOrder(Order order) {
// Order processing logic
}
}

public class PaymentProcessing {
public void processPayment(Payment payment) {
// Payment processing logic
}
}

public class ShippingProcessing {
public void processShipping(Order order) {
// Shipping processing logic
}
}

Facade:

public class OrderFacade {
private OrderProcessing orderProcessing = new OrderProcessing();
private PaymentProcessing paymentProcessing = new PaymentProcessing();
private ShippingProcessing shippingProcessing = new ShippingProcessing();

public void placeOrder(Order order, Payment payment) {
orderProcessing.processOrder(order);
paymentProcessing.processPayment(payment);
shippingProcessing.processShipping(order);
}
}
  • Exercise 3: Decorator Pattern:

    Given:

public interface Car {
void assemble();
}

public class BasicCar implements Car {
@Override
public void assemble() {
System.out.print("Basic Car.");
}
}

Decorator:

public class CarDecorator implements Car {
protected Car car;

public CarDecorator(Car car) {
this.car = car;
}

@Override
public void assemble() {
this.car.assemble();
}
}

public class SportsCar extends CarDecorator {
public SportsCar(Car car) {
super(car);
}

@Override
public void assemble() {
super.assemble();
System.out.print(" Adding features of Sports Car.");
}
}

public class LuxuryCar extends CarDecorator {
public LuxuryCar(Car car) {
super(car);
}

@Override
public void assemble() {
super.assemble();
System.out.print(" Adding features of Luxury Car.");
}
}

Sample Projects

  • Project 1: E-commerce System:
    • Description: Design an e-commerce system with separate classes for order processing, payment handling, inventory management, and user authentication. Each class should have a single responsibility.
    • Example:
public class OrderService {
public void processOrder(Order order) {
// Order processing logic
}
}

public class PaymentService {
public void handlePayment(Payment payment) {
// Payment handling logic
}
}

public class InventoryService {
public void updateInventory(Order order) {
// Inventory management logic
}
}

public class UserService {
public void authenticateUser(String username, String password) {
// User authentication logic
}
}
  • Project 2: Blogging Platform:
    • Description: Build a blogging platform with distinct classes for post management, comment handling, user profiles, and notification services. Adhere to SRP for each class.
    • Example:
public class PostService {
public void createPost(Post post) {
// Post creation logic
}
}

public class CommentService {
public void addComment(Comment comment) {
// Comment handling logic
}
}

public class UserProfileService {
public void updateUserProfile(User user) {
// User profile management logic
}
}

public class NotificationService {
public void sendNotification(Notification notification) {
// Notification logic
}
}
  • Project 3: Task Management App:
    • Description: Develop a task management application where classes are responsible for task creation, task tracking, user management, and reporting. Ensure each class has one responsibility.
    • Example:
public class TaskService {
public void createTask(Task task) {
// Task creation logic
}
}

public class TaskTrackingService {
public void trackTask(Task task) {
// Task tracking logic
}
}

public class UserService {
public void manageUser(User user) {
// User management logic
}
}

public class ReportingService {
public void generateReport() {
// Reporting logic
}
}

Quizzes

  • Quiz 1: Identifying Responsibilities:
    • Question: Given the following class, identify its responsibilities and suggest how to refactor it according to SRP.
public class LibraryService {
public void addBook(Book book) {
// Add book logic
}

public void issueBook(Book book, User user) {
// Issue book logic
}

public void returnBook(Book book, User user) {
// Return book logic
}

public void sendNotification(User user, String message) {
// Send notification logic
}
}
  • Answer:
public class BookService {
public void addBook(Book book) {
// Add book logic
}

public void issueBook(Book book, User user) {
// Issue book logic
}

public void returnBook(Book book, User user) {
// Return book logic
}
}

public class NotificationService {
public void sendNotification(User user, String message) {
// Send notification logic
}
}
  • Quiz 2: Design Patterns and SRP:

    • Question: How do the Facade, Adapter, and Decorator patterns relate to SRP? Provide examples.
    • Answer:
      • Facade Pattern: Simplifies a complex subsystem by providing a unified interface. Each class within the subsystem adheres to SRP.
      • Adapter Pattern: Allows incompatible interfaces to work together. Adapters convert one interface into another without altering the original classes, each of which has a single responsibility.
      • Decorator Pattern: Adds behavior to objects dynamically. Each decorator class and the original class follow SRP, making it easy to extend functionality in a modular way.
  • Quiz 3: Integration with SOLID Principles:

    • Question: How does SRP integrate with other SOLID principles like OCP, DIP, and ISP? Provide examples.
    • Answer:
      • OCP: By adhering to SRP, classes can be extended with new functionality without modifying existing code, supporting the Open/Closed Principle.
      • DIP: SRP facilitates Dependency Inversion by ensuring that high-level modules do not depend on low-level modules but rather on abstractions. Clear, single-responsibility classes make it easier to define these abstractions.
      • ISP: SRP promotes the use of specific, client-focused interfaces rather than a single general-purpose interface, aligning with the Interface Segregation Principle.

Multiple-Choice Questions (MCQs)

  • MCQ 1: What is the primary goal of the Single Responsibility Principle (SRP)?

    • A) To ensure a class has multiple responsibilities
    • B) To ensure a class has only one reason to change
    • C) To allow a class to handle both data and logic
    • D) To create large, monolithic classes

    Answer: B) To ensure a class has only one reason to change

  • MCQ 2: Which design pattern is most aligned with SRP?

    • A) Singleton Pattern
    • B) Observer Pattern
    • C) Facade Pattern
    • D) Strategy Pattern

    Answer: C) Facade Pattern

  • MCQ 3: What is a common pitfall when applying SRP?

    • A) Creating classes with multiple responsibilities
    • B) Overly fragmenting the codebase with too many small classes
    • C) Ignoring the need for class cohesion
    • D) All of the above

    Answer: D) All of the above