🇮🇳
🇮🇳
Republic Day Special Offer!Get 20% OFF on all courses
Enroll Now
P
Prakalpana
📚Learn
Code Your Future
System Design⏱️ 18 min read📅 Dec 29

LLD: Design Library Management System - Complete OOP

MP
Meera PatelSenior Developer
📑 Contents (8 sections)

📌Problem Statement

Design a library management system for issuing and returning books.

📌Requirements

  • Add/remove books
  • Register members
  • Issue and return books
  • Search books by title/author/ISBN
  • Calculate fines for late returns
  • Reserve books
  • 📌Class Design

    Core Entities

    public class Book {
    private String isbn;
    private String title;
    private String author;
    private String publisher;
    private int totalCopies;
    private int availableCopies;
    private BookCategory category;
    public boolean isAvailable() {
    return availableCopies > 0;
    }
    public void issueBook() {
    if (availableCopies <= 0) {
    throw new BookNotAvailableException(isbn);
    }
    availableCopies--;
    }
    public void returnBook() {
    if (availableCopies >= totalCopies) {
    throw new InvalidReturnException(isbn);
    }
    availableCopies++;
    }
    }
    public class Member {
    private String memberId;
    private String name;
    private String email;
    private MembershipType type;
    private LocalDate membershipExpiry;
    private List<BookIssue> currentIssues;
    private double outstandingFine;
    public int getMaxBooksAllowed() {
    return type.getMaxBooks();
    }
    public boolean canIssueBook() {
    return membershipExpiry.isAfter(LocalDate.now())
    && currentIssues.size() < getMaxBooksAllowed()
    && outstandingFine == 0;
    }
    }

    Issue and Return

    public class BookIssue {
    private String issueId;
    private Book book;
    private Member member;
    private LocalDate issueDate;
    private LocalDate dueDate;
    private LocalDate returnDate;
    private double fineAmount;
    private IssueStatus status;
    public BookIssue(Book book, Member member, int daysAllowed) {
    this.issueId = UUID.randomUUID().toString();
    this.book = book;
    this.member = member;
    this.issueDate = LocalDate.now();
    this.dueDate = issueDate.plusDays(daysAllowed);
    this.status = IssueStatus.ISSUED;
    }
    public double returnBook() {
    this.returnDate = LocalDate.now();
    this.status = IssueStatus.RETURNED;
    if (returnDate.isAfter(dueDate)) {
    long daysLate = ChronoUnit.DAYS.between(dueDate, returnDate);
    this.fineAmount = daysLate * FineCalculator.DAILY_FINE;
    }
    return fineAmount;
    }
    }

    Library Service

    public class LibraryService {
    private BookRepository bookRepository;
    private MemberRepository memberRepository;
    private IssueRepository issueRepository;
    private ReservationService reservationService;
    public BookIssue issueBook(String memberId, String isbn) {
    Member member = memberRepository.findById(memberId);
    Book book = bookRepository.findByIsbn(isbn);
    if (!member.canIssueBook()) {
    throw new MemberNotEligibleException(memberId);
    }
    if (!book.isAvailable()) {
    throw new BookNotAvailableException(isbn);
    }
    book.issueBook();
    BookIssue issue = new BookIssue(book, member, member.getMaxDays());
    issueRepository.save(issue);
    member.getCurrentIssues().add(issue);
    return issue;
    }
    public double returnBook(String issueId) {
    BookIssue issue = issueRepository.findById(issueId);
    double fine = issue.returnBook();
    issue.getBook().returnBook();
    issue.getMember().getCurrentIssues().remove(issue);
    if (fine > 0) {
    issue.getMember().addFine(fine);
    }
    reservationService.notifyNextReservation(issue.getBook().getIsbn());
    return fine;
    }
    public List<Book> searchBooks(String query) {
    return bookRepository.search(query);
    }
    }

    Reservation

    public class Reservation {
    private String reservationId;
    private Book book;
    private Member member;
    private LocalDateTime reservedAt;
    private ReservationStatus status;
    }
    public class ReservationService {
    private Map<String, Queue<Reservation>> reservationQueues;
    public Reservation reserveBook(String memberId, String isbn) {
    Book book = bookRepository.findByIsbn(isbn);
    Member member = memberRepository.findById(memberId);
    Reservation reservation = new Reservation(book, member);
    reservationQueues.computeIfAbsent(isbn, k -> new LinkedList<>()).add(reservation);
    return reservation;
    }
    public void notifyNextReservation(String isbn) {
    Queue<Reservation> queue = reservationQueues.get(isbn);
    if (queue != null && !queue.isEmpty()) {
    Reservation next = queue.poll();
    notificationService.notifyBookAvailable(next.getMember(), next.getBook());
    }
    }
    }

    📌Design Patterns

  • 1Repository Pattern: Data access
  • 2Observer Pattern: Reservation notifications
  • 3Strategy Pattern: Fine calculation
  • Asked at Infosys, TCS, and Wipro interviews.

    MP

    Written by

    Meera Patel

    Senior Developer

    🚀 Master System Design

    Join 500+ developers

    Explore Courses →
    Chat on WhatsApp