Architecting the System
To build a functional library management system in Java, we need to organize our code in to distinct modules: data models for books, user hierarchies for different access levels, and a decoupled set of operations. This approach leverages Object-Oriented Programming (OOP) concepts like inheritance, polymorphism, and encapsulation.
Core Data Models
The foundation of the system consists of the Book class, which represents individual titles, and the LibraryShelf class, which manages the clolection.
The Book Class
This entity encapsulates the properties of a book, including its title, author, price, category, and availability status.
public class Book {
private String title;
private String author;
private double price;
private String category;
private boolean isLoaned;
public Book(String title, String author, double price, String category) {
this.title = title;
this.author = author;
this.price = price;
this.category = category;
this.isLoaned = false;
}
// Getters and Setters
public String getTitle() { return title; }
public void setTitle(String title) { this.title = title; }
public String getAuthor() { return author; }
public double getPrice() { return price; }
public boolean isLoaned() { return isLoaned; }
public void setLoaned(boolean loaned) { isLoaned = loaned; }
@Override
public String toString() {
return String.format("Title: %-15s | Author: %-10s | Price: %-5.2f | Type: %-10s | Status: %s",
title, author, price, category, (isLoaned ? "Borrowed" : "Available"));
}
}
The LibraryShelf Class
The LibraryShelf acts as a container for our book objects, providing methods to access specific slots and track the total count.
public class LibraryShelf {
private Book[] inventory = new Book[20];
private int currentBookCount;
public LibraryShelf() {
inventory[0] = new Book("Java Basics", "John Smith", 45.0, "Tech");
inventory[1] = new Book("Clean Code", "Robert Martin", 55.0, "Tech");
inventory[2] = new Book("The Hobbit", "Tolkien", 30.0, "Fiction");
this.currentBookCount = 3;
}
public Book getBookInstance(int index) {
return inventory[index];
}
public void updateBook(int index, Book book) {
inventory[index] = book;
}
public int getCurrentBookCount() {
return currentBookCount;
}
public void setCurrentBookCount(int count) {
this.currentBookCount = count;
}
public int getCapacity() {
return inventory.length;
}
}
User Management and Inheritance
The system distinguishes between administrative users and regular patrons. We use an abstract LibraryUser class to define common traits.
Abstract User Definition
public abstract class LibraryUser {
protected String username;
protected IAction[] actions;
public LibraryUser(String username) {
this.username = username;
}
public abstract int displayMenu();
public void executeAction(int choice, LibraryShelf shelf) {
if (choice >= 0 && choice < actions.length) {
actions[choice].perform(shelf);
} else {
System.out.println("Invalid option.");
}
}
}
Admin and Regular User Implementations
Each user type initializes its own set of available operations in its constructor.
public class Administrator extends LibraryUser {
public Administrator(String username) {
super(username);
this.actions = new IAction[]{
new ShutdownAction(),
new SearchAction(),
new InsertAction(),
new RemoveAction(),
new ListAllAction()
};
}
@Override
public int displayMenu() {
System.out.println("--- Admin Console: " + this.username + " ---");
System.out.println("1. Find Book | 2. Add Book | 3. Delete Book | 4. Show All | 0. Exit");
return new java.util.Scanner(System.in).nextInt();
}
}
public class RegularMember extends LibraryUser {
public RegularMember(String username) {
super(username);
this.actions = new IAction[]{
new ShutdownAction(),
new SearchAction(),
new LoanAction(),
new ReturnAction()
};
}
@Override
public int displayMenu() {
System.out.println("--- Member Portal: " + this.username + " ---");
System.out.println("1. Find Book | 2. Borrow | 3. Return | 0. Exit");
return new java.util.Scanner(System.in).nextInt();
}
}
Functional Operations
By using an interface, we can treat every library action (adding, deleting, etc.) as a polymorphic object.
The Action Interface
public interface IAction {
void perform(LibraryShelf shelf);
}
Implementing the Add Operation
public class InsertAction implements IAction {
@Override
public void perform(LibraryShelf shelf) {
if (shelf.getCurrentBookCount() == shelf.getCapacity()) {
System.out.println("Shelf is full!");
return;
}
java.util.Scanner input = new java.util.Scanner(System.in);
System.out.print("Enter Title: ");
String t = input.nextLine();
System.out.print("Enter Author: ");
String a = input.nextLine();
System.out.print("Enter Price: ");
double p = input.nextDouble();
input.nextLine(); // consume newline
System.out.print("Enter Category: ");
String c = input.nextLine();
Book newBook = new Book(t, a, p, c);
int pos = shelf.getCurrentBookCount();
shelf.updateBook(pos, newBook);
shelf.setCurrentBookCount(pos + 1);
System.out.println("Book added successfully.");
}
}
Implementing the Loan Operation
public class LoanAction implements IAction {
@Override
public void perform(LibraryShelf shelf) {
System.out.print("Enter the title of the book to borrow: ");
String target = new java.util.Scanner(System.in).nextLine();
for (int i = 0; i < shelf.getCurrentBookCount(); i++) {
Book b = shelf.getBookInstance(i);
if (b.getTitle().equalsIgnoreCase(target)) {
if (b.isLoaned()) {
System.out.println("This book is already out on loan.");
return;
}
b.setLoaned(true);
System.out.println("Loan processed successfully.");
return;
}
}
System.out.println("Book not found.");
}
}
The Main Controller
The entry point manages the login process and runs the main execution loop, passing the user's menu choice to the execution engine.
public class SystemApp {
public static LibraryUser authenticate() {
java.util.Scanner scanner = new java.util.Scanner(System.in);
System.out.print("Enter Name: ");
String name = scanner.nextLine();
System.out.println("Select Identity: 1. Admin | 2. Member");
int role = scanner.nextInt();
return (role == 1) ? new Administrator(name) : new RegularMember(name);
}
public static void main(String[] args) {
LibraryShelf myShelf = new LibraryShelf();
LibraryUser activeUser = authenticate();
while (true) {
int command = activeUser.displayMenu();
activeUser.executeAction(command, myShelf);
}
}
}