> For the complete documentation index, see [llms.txt](https://mayanktyagi3111.gitbook.io/interview-prep/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://mayanktyagi3111.gitbook.io/interview-prep/lld-questions/library-management-system.md).

# Library Management System

#### Low-Level Design (LLD) for a **Library Management System** in Java

The **Library Management System** is a software application designed to manage the day-to-day operations of a library, including tracking books, managing members, and overseeing the lending and returning of books. The system should also handle overdue books, fines, and send reminders for due or overdue returns.

In this LLD, we will cover the following core functionalities:

* **Entities and Relationships**: What are the main entities (books, members, loans, etc.) and how do they relate to each other?
* **Book Lending and Returning**: How will we handle lending and returning of books, and track the process efficiently?
* **Overdue Management**: How will we handle overdue books, manage fines, and send reminders?
* **Design Patterns Used**: We'll incorporate several design patterns such as **Factory Pattern**, **Observer Pattern**, **Strategy Pattern**, and **Singleton Pattern** to create a modular, scalable design.

***

#### **Key Entities and Relationships**

**Entities:**

* **Book**: Represents a book in the library, with properties like title, author, ISBN, availability status, etc.
* **Member**: Represents a library member, with properties like name, membership ID, and a list of books currently borrowed.
* **Loan**: Represents a loan transaction, keeping track of the book, the member, the due date, and the status (lent, returned, overdue).
* **Fine**: Represents fines associated with overdue books.

**Relationships:**

* A **Member** can borrow multiple **Books** through **Loans**.
* A **Book** can be associated with multiple **Loans** over time.
* **Loans** track the lending date, due date, and whether the book is overdue or returned.
* **Fines** are associated with **Loans** if a book is returned past the due date.

#### **Design Patterns Used**

* **Factory Pattern**: To create different entities like `Book`, `Member`, and `Loan`.
* **Observer Pattern**: To send notifications (like reminders for overdue books).
* **Strategy Pattern**: For calculating fines based on different rules.
* **Singleton Pattern**: To manage the library system and ensure only one instance of the library exists.

***

#### **Classes and Data Structures**

**1. Book Class**

The **Book** class represents a book in the library system.

```java
class Book {
    private String title;
    private String author;
    private String ISBN;
    private boolean isAvailable;

    public Book(String title, String author, String ISBN) {
        this.title = title;
        this.author = author;
        this.ISBN = ISBN;
        this.isAvailable = true; // Book is available by default
    }

    public boolean isAvailable() {
        return isAvailable;
    }

    public void setAvailability(boolean availability) {
        this.isAvailable = availability;
    }

    public String getTitle() {
        return title;
    }

    public String getISBN() {
        return ISBN;
    }
}
```

**2. Member Class**

The **Member** class represents a library member and their current loans.

```java
import java.util.List;

class Member {
    private String name;
    private String memberId;
    private List<Loan> loans;

    public Member(String name, String memberId) {
        this.name = name;
        this.memberId = memberId;
    }

    public void borrowBook(Book book, Library library) {
        if (book.isAvailable()) {
            Loan loan = library.issueBook(this, book);
            loans.add(loan);
        } else {
            System.out.println("Book is not available for borrowing.");
        }
    }

    public void returnBook(Book book, Library library) {
        Loan loan = findLoanForBook(book);
        if (loan != null) {
            loan.setReturned(true);
            library.receiveBook(this, loan);
        } else {
            System.out.println("This book is not on loan to this member.");
        }
    }

    private Loan findLoanForBook(Book book) {
        for (Loan loan : loans) {
            if (loan.getBook().equals(book) && !loan.isReturned()) {
                return loan;
            }
        }
        return null;
    }

    public String getName() {
        return name;
    }

    public String getMemberId() {
        return memberId;
    }
}
```

**3. Loan Class**

The **Loan** class represents a transaction where a book is borrowed by a member.

```java
import java.util.Date;

class Loan {
    private Book book;
    private Member member;
    private Date issueDate;
    private Date dueDate;
    private boolean isReturned;

    public Loan(Book book, Member member, Date issueDate, Date dueDate) {
        this.book = book;
        this.member = member;
        this.issueDate = issueDate;
        this.dueDate = dueDate;
        this.isReturned = false;
    }

    public boolean isOverdue() {
        return !isReturned && new Date().after(dueDate);
    }

    public Book getBook() {
        return book;
    }

    public Date getDueDate() {
        return dueDate;
    }

    public boolean isReturned() {
        return isReturned;
    }

    public void setReturned(boolean isReturned) {
        this.isReturned = isReturned;
    }
}
```

**4. Fine Class**

The **Fine** class represents fines for overdue books.

```java
class Fine {
    private Loan loan;
    private double amount;

    public Fine(Loan loan, double amount) {
        this.loan = loan;
        this.amount = amount;
    }

    public Loan getLoan() {
        return loan;
    }

    public double getAmount() {
        return amount;
    }
}
```

**5. Library Class (Singleton Pattern)**

The **Library** class is the central class that manages the system and ensures only one instance of the library exists.

```java
import java.util.*;

class Library {
    private static Library instance;
    private Map<String, Book> books;
    private List<Loan> activeLoans;

    private Library() {
        books = new HashMap<>();
        activeLoans = new ArrayList<>();
    }

    public static Library getInstance() {
        if (instance == null) {
            instance = new Library();
        }
        return instance;
    }

    public void addBook(Book book) {
        books.put(book.getISBN(), book);
    }

    public Loan issueBook(Member member, Book book) {
        Date issueDate = new Date();
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(issueDate);
        calendar.add(Calendar.DAY_OF_YEAR, 14); // Default 14-day loan
        Date dueDate = calendar.getTime();

        Loan loan = new Loan(book, member, issueDate, dueDate);
        activeLoans.add(loan);
        book.setAvailability(false); // Book is now unavailable
        return loan;
    }

    public void receiveBook(Member member, Loan loan) {
        loan.setReturned(true);
        loan.getBook().setAvailability(true); // Mark book as available
    }

    public List<Fine> checkOverdueBooks() {
        List<Fine> fines = new ArrayList<>();
        for (Loan loan : activeLoans) {
            if (loan.isOverdue()) {
                double fineAmount = calculateFine(loan);
                fines.add(new Fine(loan, fineAmount));
            }
        }
        return fines;
    }

    private double calculateFine(Loan loan) {
        long daysOverdue = (new Date().getTime() - loan.getDueDate().getTime()) / (1000 * 60 * 60 * 24);
        return daysOverdue * 1.0; // Fine of $1 per day
    }
}
```

**6. FineCalculator Strategy (Strategy Pattern)**

The **FineCalculator** class implements the **Strategy Pattern** to calculate fines differently based on rules or conditions.

```java
interface FineCalculator {
    double calculateFine(Loan loan);
}

class StandardFineCalculator implements FineCalculator {
    @Override
    public double calculateFine(Loan loan) {
        long daysOverdue = (new Date().getTime() - loan.getDueDate().getTime()) / (1000 * 60 * 60 * 24);
        return daysOverdue * 1.0; // $1 per day
    }
}

class PremiumFineCalculator implements FineCalculator {
    @Override
    public double calculateFine(Loan loan) {
        return 0; // No fine for premium members
    }
}
```

**7. Notification System (Observer Pattern)**

The **NotificationSystem** uses the **Observer Pattern** to notify members about overdue books and fines.

```java
interface Observer {
    void update(String message);
}

class MemberObserver implements Observer {
    private Member member;

    public MemberObserver(Member member) {
        this.member = member;
    }

    @Override
    public void update(String message) {
        System.out.println("Notification to " + member.getName() + ": " + message);
    }
}

class NotificationSystem {
    private List<Observer> observers = new ArrayList<>();

    public void addObserver(Observer observer) {
        observers.add(observer);
    }

    public void notifyObservers(String message) {
        for (Observer observer : observers) {
            observer.update(message);
        }
    }
}
```

#### **Main Class to Demonstrate the System**

```java
public class LibraryApplication {
    public static void main(String[] args) {
        // Initialize the library
        Library library = Library.getInstance();

        // Create some books
        Book book1 = new Book("The Great Gatsby", "F. Scott Fitzgerald", "9780743273565");
        Book book2 = new Book("1984", "George Orwell", "9780451524935");
        
        library.addBook(book1);
        library.addBook(book2);

        // Create a member
        Member member = new Member("John Doe", "M001");

        // Borrow books
        member.borrowBook(book1, library);
        
        // Create a notification system
        NotificationSystem notificationSystem = new NotificationSystem();
        notificationSystem.addObserver(new MemberObserver(member));
        
        // Check for overdue books (just after borrowing)
        List<Fine> fines = library.checkOverdueBooks();
        for (Fine fine : fines) {
            notificationSystem.notifyObservers("Fine for overdue book: " + fine.getAmount());
        }
    }
}
```

***

#### **Design Patterns Used**

1. **Factory Pattern**: The `LibraryFactory` or `UserFactory` class (not explicitly shown in code) could be used to create different entities like `Book`, `Member`, `Loan`, and `Fine` objects dynamically.
2. **Strategy Pattern**: The `FineCalculator` interface and its implementations (`StandardFineCalculator`, `PremiumFineCalculator`) allow the calculation of fines to be easily modified or extended.
3. **Observer Pattern**: The `NotificationSystem` and `Observer` pattern are used to notify members about overdue books and fines.
4. **Singleton Pattern**: The `Library` class is implemented as a singleton to ensure only one instance of the library exists.

***

#### **Conclusion**

The **Library Management System** uses design patterns like **Factory**, **Strategy**, **Observer**, and **Singleton** to ensure modularity, flexibility, and maintainability. It manages entities such as **Books**, **Members**, **Loans**, and **Fines**, while efficiently tracking book lending, returns, overdue management, and sending notifications to members.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://mayanktyagi3111.gitbook.io/interview-prep/lld-questions/library-management-system.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
