Designing a Library Management System


Requirements:

Sequnece Diagram
cache
High-Level Design:

To design a Library Management System, we will create several classes to represent the system’s components, such as:


Class Design:

Code Implementation:
import java.util.*;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

// Class representing Book
class Book {
    private String title;
    private String author;
    private String isbn;
    private int publicationYear;
    private boolean available;

    public Book(String title, String author, String isbn, int publicationYear) {
        this.title = title;
        this.author = author;
        this.isbn = isbn;
        this.publicationYear = publicationYear;
        this.available = true;
    }

    public String getTitle() {
        return title;
    }

    public String getIsbn() {
        return isbn;
    }

    public boolean isAvailable() {
        return available;
    }

    public void borrowBook() {
        this.available = false;
    }

    public void returnBook() {
        this.available = true;
    }
}
// Class representing Member
class Member {
    private String name;
    private String memberId;
    private String contactInfo;
    private List<Book> borrowedBooks;

    public Member(String name, String memberId, String contactInfo) {
        this.name = name;
        this.memberId = memberId;
        this.contactInfo = contactInfo;
        this.borrowedBooks = new ArrayList<>();
    }

    public String getMemberId() {
        return memberId;
    }

    public List<Book> getBorrowedBooks() {
        return borrowedBooks;
    }

    public void borrowBook(Book book) {
        borrowedBooks.add(book);
    }

    public void returnBook(Book book) {
        borrowedBooks.remove(book);
    }

    public boolean hasReachedMaxBooks(int maxBooks) {
        return borrowedBooks.size() >= maxBooks;
    }
}
// Class representing Transaction (Borrow or Return)
class Transaction {
    private Book book;
    private Member member;
    private Date transactionDate;
    private String transactionType;  // "borrow" or "return"

    public Transaction(Book book, Member member, String transactionType) {
        this.book = book;
        this.member = member;
        this.transactionType = transactionType;
        this.transactionDate = new Date();
    }

    public void displayTransaction() {
        System.out.println("Transaction: " + transactionType + " | Book: " + book.getTitle() +
                " | Member: " + member.getMemberId() + " | Date: " + transactionDate);
    }
}
// Class representing Library
class Library {
    private Map catalog;
    private Map members;
    private final int MAX_BOOKS = 5;  // Maximum books a member can borrow at once
    private final Lock lock;

    public Library() {
        catalog = new HashMap<>();
        members = new HashMap<>();
        lock = new ReentrantLock();
    }

    public void addBook(Book book) {
        catalog.put(book.getIsbn(), book);
    }

    public void removeBook(String isbn) {
        catalog.remove(isbn);
    }

    public void addMember(Member member) {
        members.put(member.getMemberId(), member);
    }

    public void borrowBook(String memberId, String isbn) {
        lock.lock();
        try {
            Member member = members.get(memberId);
            Book book = catalog.get(isbn);

            if (member != null && book != null) {
                if (book.isAvailable() && !member.hasReachedMaxBooks(MAX_BOOKS)) {
                    book.borrowBook();
                    member.borrowBook(book);
                    Transaction transaction = new Transaction(book, member, "borrow");
                    transaction.displayTransaction();
                } else if (!book.isAvailable()) {
                    System.out.println("Book is already borrowed.");
                } else {
                    System.out.println("Member has reached the borrowing limit.");
                }
            } else {
                System.out.println("Member or Book not found.");
            }
        } finally {
            lock.unlock();
        }
    }

    public void returnBook(String memberId, String isbn) {
        lock.lock();
        try {
            Member member = members.get(memberId);
            Book book = catalog.get(isbn);

            if (member != null && book != null && member.getBorrowedBooks().contains(book)) {
                book.returnBook();
                member.returnBook(book);
                Transaction transaction = new Transaction(book, member, "return");
                transaction.displayTransaction();
            } else {
                System.out.println("Invalid return request.");
            }
        } finally {
            lock.unlock();
        }
    }
}
// Main class to simulate Library Management System
public class LibraryManagementApp {
    public static void main(String[] args) {
        Library library = new Library();

        // Adding books to library
        Book book1 = new Book("Java Programming", "Author A", "12345", 2020);
        Book book2 = new Book("Data Structures", "Author B", "67890", 2018);
        library.addBook(book1);
        library.addBook(book2);

        // Adding members
        Member member1 = new Member("Alice", "M001", "alice@email.com");
        Member member2 = new Member("Bob", "M002", "bob@email.com");
        library.addMember(member1);
        library.addMember(member2);

        // Borrow books
        library.borrowBook("M001", "12345");  // Alice borrows Java Programming
        library.borrowBook("M002", "67890");  // Bob borrows Data Structures

        // Returning books
        library.returnBook("M001", "12345");  // Alice returns Java Programming
    }
}
Sample Input:
    // Adding books to the library
    Book book1 = new Book("Java Programming", "Author A", "12345", 2020);
    Book book2 = new Book("Data Structures", "Author B", "67890", 2018);
    library.addBook(book1);
    library.addBook(book2);

    // Adding members
    Member member1 = new Member("Alice", "M001", "alice@email.com");
    Member member2 = new Member("Bob", "M002", "bob@email.com");
    library.addMember(member1);
    library.addMember(member2);

    // Borrow books
    library.borrowBook("M001", "12345");  // Alice borrows Java Programming
    library.borrowBook("M002", "67890");  // Bob borrows Data Structures

    // Returning books
    library.returnBook("M001", "12345");  // Alice returns Java Programming
    
Sample Output:
    // Output after Alice borrows Java Programming
    Transaction: borrow | Book: Java Programming | Member: M001 | Date: 

    // Output after Bob borrows Data Structures
    Transaction: borrow | Book: Data Structures | Member: M002 | Date: 

    // Output after Alice returns Java Programming
    Transaction: return | Book: Java Programming | Member: M001 | Date: 

    // If Bob tries to borrow another book while having already borrowed the maximum allowed books
    Transaction: borrow | Book: Data Structures | Member: M002 | Date: 
    Book is already borrowed.
    
Explanation of the Code:

Design Considerations: