Core classes for a library system, reservation queueing when a book is checked out, and fine calculation as a pluggable strategy.
Published September 23, 2026
class Book {
private final String isbn;
private final String title;
private BookStatus status = BookStatus.AVAILABLE; // AVAILABLE, CHECKED_OUT, RESERVED
}
class Member {
private final String memberId;
private final List<Loan> activeLoans = new ArrayList<>();
}
class Loan {
private final Book book;
private final Member member;
private final Instant checkoutDate;
private final Instant dueDate;
private Instant returnDate; // null until returned
}
class Library {
private final Map<String, Book> catalog;
private final Map<String, Queue<Member>> reservationQueues = new HashMap<>(); // per book ISBN
}
Loan is a deliberate separate class rather than a field on Book — a book can have many loans over its lifetime, and keeping loan history (not just current status) requires a record per checkout, not a single mutable field.
class Library {
Optional<Book> checkout(String isbn, Member member) {
Book book = catalog.get(isbn);
if (book.getStatus() != BookStatus.AVAILABLE) return Optional.empty();
book.setStatus(BookStatus.CHECKED_OUT);
loans.add(new Loan(book, member, Instant.now(), Instant.now().plus(Duration.ofDays(14))));
return Optional.of(book);
}
void reserve(String isbn, Member member) {
reservationQueues.computeIfAbsent(isbn, k -> new LinkedList<>()).add(member); // FIFO — first reservation, first served
}
void returnBook(String isbn) {
Book book = catalog.get(isbn);
Queue<Member> queue = reservationQueues.get(isbn);
if (queue != null && !queue.isEmpty()) {
Member next = queue.poll();
book.setStatus(BookStatus.RESERVED); // held for the next member in line, not immediately AVAILABLE
notifyMemberBookReady(next, book);
} else {
book.setStatus(BookStatus.AVAILABLE);
}
}
}
The RESERVED status (distinct from AVAILABLE) matters: a returned book with a waiting reservation queue shouldn't be checkoutable by a walk-in member ahead of whoever reserved it first — this is the detail that separates a design that merely tracks availability from one that correctly models fairness.
interface FineStrategy { double calculateFine(Loan loan); }
class StandardFineStrategy implements FineStrategy {
private static final double DAILY_RATE = 0.25;
public double calculateFine(Loan loan) {
long overdueDays = Math.max(0, Duration.between(loan.getDueDate(), Instant.now()).toDays());
return overdueDays * DAILY_RATE;
}
}
class CappedFineStrategy implements FineStrategy {
private final FineStrategy delegate;
private final double cap;
public double calculateFine(Loan loan) { return Math.min(delegate.calculateFine(loan), cap); } // Decorator over a Strategy
}
Same Strategy Pattern separation used throughout this course: fine policy can differ per library branch or member type without Library's checkout/return logic ever changing. CappedFineStrategy wrapping another FineStrategy is worth noticing — it's Decorator applied to a Strategy object, showing the two patterns aren't mutually exclusive.
Q: What happens if a member never picks up a RESERVED book? A: A real system needs a timeout — after N days in RESERVED status unclaimed, the book reverts to AVAILABLE (or offers to the next person in the reservation queue), which would be implemented as a scheduled check rather than something triggered by a user action.
Q: Why is reservationQueues keyed by ISBN rather than by a specific physical book copy? A: This design assumes reservations are for a title, not a specific physical copy — if a library has multiple copies of the same ISBN, any returned copy can satisfy the next reservation, which is the more realistic and more useful behavior than binding a reservation to one specific physical book.
Q: How would you extend this to support multiple copies of the same book? A: Separate the concept of a Book (the title/metadata) from a BookCopy (one physical, individually trackable instance with its own status) — Book would hold a List<BookCopy>, and checkout logic would search for any AVAILABLE copy rather than checking a single book's status directly.