Skip to content
Low Level Design Mastery Logo
LowLevelDesign Mastery

All Together

See all relationships working together in a real-world system.

Let’s build a complete Library Management System that demonstrates all four class relationships working together.

We’ll design a library system with:

  • Library (main system)
  • Book (items in library)
  • Member (people who borrow books)
  • Librarian (staff managing library)
  • Loan (borrowing record)
  • Fine (penalty for late returns)
library_system_complete.py
from abc import ABC, abstractmethod
from datetime import datetime, timedelta
# ========== INHERITANCE ==========
class Person(ABC):
"""Base class using Inheritance"""
def __init__(self, name: str, email: str):
self.name = name
self.email = email
@abstractmethod
def get_role(self):
pass
# Inheritance - Member IS-A Person
class Member(Person):
def __init__(self, name: str, email: str, member_id: str):
super().__init__(name, email)
self.member_id = member_id
self.loans = [] # COMPOSITION - loans belong to member
def get_role(self):
return "Member"
def borrow_book(self, book, librarian):
# DEPENDENCY - uses Book and Librarian temporarily
loan = Loan(self, book, librarian)
self.loans.append(loan) # COMPOSITION
return loan
# Inheritance - Librarian IS-A Person
class Librarian(Person):
def __init__(self, name: str, email: str, employee_id: str):
super().__init__(name, email)
self.employee_id = employee_id
def get_role(self):
return "Librarian"
def process_return(self, loan):
# DEPENDENCY - uses Loan temporarily
loan.return_book()
if loan.is_overdue():
fine = Fine(loan) # COMPOSITION - fine created with loan
loan.fine = fine
# ========== COMPOSITION ==========
class Book:
"""Book is part of Library - COMPOSITION"""
def __init__(self, isbn: str, title: str, author: str):
self.isbn = isbn
self.title = title
self.author = author
self.available = True
# COMPOSITION - Loan belongs to Member
class Loan:
def __init__(self, member, book, librarian):
self.member = member # ASSOCIATION - references member
self.book = book # ASSOCIATION - references book
self.librarian = librarian # ASSOCIATION - references librarian
self.borrow_date = datetime.now()
self.due_date = self.borrow_date + timedelta(days=14)
self.return_date = None
self.fine = None # COMPOSITION - optional fine
def return_book(self):
self.return_date = datetime.now()
self.book.available = True
def is_overdue(self):
if self.return_date:
return self.return_date > self.due_date
return datetime.now() > self.due_date
# COMPOSITION - Fine belongs to Loan
class Fine:
def __init__(self, loan):
self.loan = loan # ASSOCIATION - references loan
days_overdue = (datetime.now() - loan.due_date).days
self.amount = days_overdue * 0.50 # $0.50 per day
# ========== COMPOSITION & AGGREGATION ==========
class Library:
"""Library contains Books (COMPOSITION) and has Members/Librarians (AGGREGATION)"""
def __init__(self, name: str):
self.name = name
self.books = [] # COMPOSITION - books belong to library
self.members = [] # AGGREGATION - members can exist independently
self.librarians = [] # AGGREGATION - librarians can exist independently
def add_book(self, book):
self.books.append(book) # COMPOSITION
def register_member(self, member):
self.members.append(member) # AGGREGATION
def hire_librarian(self, librarian):
self.librarians.append(librarian) # AGGREGATION
def find_book(self, isbn: str):
"""DEPENDENCY - uses string parameter"""
for book in self.books:
if book.isbn == isbn:
return book
return None
# ========== USAGE ==========
# Create library
library = Library("City Library")
# Create books (COMPOSITION - belong to library)
book1 = Book("12345", "Python Guide", "Author A")
book2 = Book("67890", "Java Guide", "Author B")
library.add_book(book1)
library.add_book(book2)
# Create members (AGGREGATION - can exist independently)
member1 = Member("Alice", "alice@example.com", "M001")
member2 = Member("Bob", "bob@example.com", "M002")
library.register_member(member1)
library.register_member(member2)
# Create librarian (AGGREGATION)
librarian = Librarian("Carol", "carol@library.com", "L001")
library.hire_librarian(librarian)
# Member borrows book (creates ASSOCIATION and COMPOSITION)
loan = member1.borrow_book(book1, librarian)
print(f"{member1.name} borrowed {book1.title}")
# Librarian processes return (uses DEPENDENCY)
librarian.process_return(loan)
print(f"Book returned. Fine: ${loan.fine.amount if loan.fine else 0:.2f}")
Diagram
  • Why: Both share common attributes (name, email) and have roles
  • Type: “Is-a” relationship
  • Why: Books are part of library, loans belong to members, fines belong to loans
  • Type: Strong ownership, cannot exist independently
  • Why: Members and librarians can exist independently (can transfer/leave)
  • Type: Weak ownership, independent lifecycle
  • Why: Loan references these classes but doesn’t own them
  • Type: “Knows-a” relationship
  • Why: Used temporarily as method parameters
  • Type: Temporary use, no storage