UML Class Diagrams: Complete Guide
What is a Class Diagram? A class diagram is a type of static structure diagram used in UML to describe the structure of a system by showing the system's classes, their attributes, methods, and the relationships among the classes.
π Table of Contents
- Access Modifiers
- Associations
- Relationships
- Dependency
- Real-World Examples
- Interview Questions
- Summary
π Access Modifiers
Access modifiers control the visibility and accessibility of class members (attributes and methods). They define which parts of your code can access specific members.
Visibility Levels
| Symbol | Name | Visibility | Use Case |
|---|---|---|---|
+ |
Public | Everywhere | General APIs, methods callers need to use |
- |
Private | Within class only | Internal implementation details |
# |
Protected | Class + Subclasses | Shared implementation for inheritance |
~ |
Package | Same package only | Internal package-level access |
π ASCII Diagram: Access Modifier Visibility
βββββββββββββββββββββββββββββββββββββββββββ
β VISIBILITY SCOPE β
βββββββββββββββββββββββββββββββββββββββββββ€
β β
β + Public β
β βββ Can be accessed from anywhere β
β βββ No restrictions β
β βββ Use for public interfaces β
β β
β # Protected β
β βββ Accessible in class + subclasses β
β βββ Hidden from outside clients β
β βββ Supports inheritance patterns β
β β
β - Private β
β βββ Only accessible within class β
β βββ Completely hidden from outside β
β βββ Best for encapsulation β
β β
β ~ Package β
β βββ Only within same package β
β βββ Cross-package access blocked β
β βββ Used for internal implementation β
β β
βββββββββββββββββββββββββββββββββββββββββββ
Example: BankAccount Class
ββββββββββββββββββββββββββββββββββ
β BankAccount β
ββββββββββββββββββββββββββββββββββ€
β Attributes: β
β + accountNumber: String βββ β
β # balance: Double βββββββββΌβββ β
β - PIN: Integer ββββββββββββΌβββΌββ€
β β β β
ββββββββββββββββββββββββββββββ€ β β
β Methods: β β β
β + deposit(amount) βββββββββββββ β
β # calculateInterest() ββββββββββ β
β - validatePIN(pin) ββββββββββββββ β
β + getBalance() β
ββββββββββββββββββββββββββββββββββ
Legend:
+ = Public (accessible everywhere)
# = Protected (for subclasses)
- = Private (internal only)
π‘ Key Principles
| Principle | Description | Benefit |
|---|---|---|
| Encapsulation | Hide implementation, expose interface | Security & flexibility |
| Least Privilege | Make members as private as possible | Reduced coupling |
| Information Hiding | Don't expose internal details | Easier maintenance |
π Associations
Association represents a relationship between two classes where one class uses or interacts with another. It indicates that objects of one class are connected to objects of another class.
π Types of Associations
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β ASSOCIATION TYPES β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β 1. Inheritance (IS-A) β¬οΈ Strong β
β ββ Child inherits from parent β
β β
β 2. Composition (HAS-A) π Strong β
β ββ Whole-Part (tightly bound) β
β β
β 3. Aggregation (HAS-A) π² Weak β
β ββ Whole-Part (loosely bound) β
β β
β 4. Simple Association β‘οΈ Medium β
β ββ Objects communicate/reference β
β β
β 5. Dependency βΆ Weak β
β ββ Temporary usage relationship β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
1οΈβ£ Inheritance (Class Association / IS-A Relationship)
Definition: A child class inherits properties and methods from a parent class. It's an IS-A relationship.
Notation: Solid line with hollow arrowhead pointing to parent class
When to Use: - Creating specialized versions of a general class - Sharing common behavior among related classes - Building class hierarchies
π Inheritance Diagram: Multi-Level Hierarchy
ββββββββββββββββββββ
β Vehicle β
ββββββββββββββββββββ€
β - speed: double β
β - color: String β
ββββββββββββββββββββ€
β + start() β
β + stop() β
β + drive() β
ββββββββββ¬ββββββββββ
β³
ββββββββββββββΌβββββββββββββ
β β β
β β β
ββββββββ΄βββββ βββββ΄ββββββ ββββ΄βββββββ
β Car β β Bike β β Truck β
βββββββββββββ€ βββββββββββ€ βββββββββββ€
β - doors β β -gears β β -cargo β
βββββββββββββ€ βββββββββββ€ βββββββββββ€
β +honk() β β+shift() β β+load() β
βββββββββββββ βββββββββββ βββββββββββ
Inheritance: Child extends Parent
Benefits:
β Code reuse
β Polymorphism
β Consistent interface
Example Code
class Vehicle:
def __init__(self, speed, color):
self.speed = speed
self.color = color
def start(self):
print("Starting engine...")
def drive(self):
print(f"Driving at {self.speed} km/h")
class Car(Vehicle): # Inherits from Vehicle
def __init__(self, speed, color, doors):
super().__init__(speed, color)
self.doors = doors
def honk(self):
print("Beep! Beep!")
# Usage
car = Car(100, "red", 4) # Car IS-A Vehicle
car.drive() # Inherits from parent
car.honk() # Own method
β οΈ Common Mistakes
- β Using inheritance when composition is better
- β Creating deep hierarchies (more than 3 levels)
- β Violating Liskov Substitution Principle
- β Use inheritance for true IS-A relationships
- β Prefer composition for HAS-A relationships
2οΈβ£ Simple Association (Object Association / HAS-A Relationship)
Definition: One object uses or references another object. It's the weakest connection between objects.
Notation: Simple line with or without arrowhead
When to Use: - Objects communicate through references - One object provides services to another - Temporary or optional relationships
π Simple Association Diagram
ββββββββββββββββ ββββββββββββββββ
β Student ββββββββββΆβ Course β
ββββββββββββββββ€ ββββββββββββββββ€
β - name β enrolls β - courseId β
β - studentId β in β - title β
ββββββββββββββββ€ ββββββββββββββββ€
β + getName() β β + getName() β
β + enroll() β ββββββββββββββββ
ββββββββββββββββ
Navigation: One-way
Student knows about Course
Course doesn't know about Student
Example Code
class Course:
def __init__(self, course_id, title):
self.course_id = course_id
self.title = title
def get_title(self):
return self.title
class Student:
def __init__(self, name, student_id):
self.name = name
self.student_id = student_id
self.courses = [] # Reference to Course objects
def enroll(self, course):
self.courses.append(course)
def get_courses(self):
return [c.get_title() for c in self.courses]
# Usage
math_course = Course(101, "Mathematics")
student = Student("John", 1)
student.enroll(math_course) # Association created
Characteristics
| Aspect | Description |
|---|---|
| Strength | Weak - no dependency on lifecycle |
| Navigation | One or Two-way |
| Multiplicity | Can be one-to-one, one-to-many, many-to-many |
| Flexibility | Highly flexible, can be changed at runtime |
3οΈβ£ Composition (Strong IS-PART-OF Relationship)
Definition: A whole-part relationship where parts cannot exist independently. The container owns the parts.
Notation: Solid line with filled diamond on the container side
When to Use: - Whole controls lifecycle of parts - Parts have no meaning outside the whole - Clear ownership and exclusive relationship
π Composition Diagram: Chair Example
ββββββββββββββββ
β Chair β (Whole)
ββββββββββββββββ€
β - color β
β - legs ββββ β
β - seat βββΌβββ€
β - arms βββ β
ββββββββββββββββ
β
/|\
/ | \
/ | \
ββββββββββββ βββββββ΄βββ ββββββββββββ
β Leg β β Seat β β Arm β
β(Part) β β(Part) β β (Part) β
ββββββββββββ ββββββββββ ββββββββββββ
Composition: Whole owns Parts
Multiplicity:
Chair has 4 Legs
Chair has 1 Seat
Chair has 2 Arms
Lifecycle: If Chair is deleted, all parts are deleted
Example Code
class Leg:
def __init__(self, material):
self.material = material
class Seat:
def __init__(self, material):
self.material = material
class Arm:
def __init__(self, material):
self.material = material
class Chair:
def __init__(self, color):
self.color = color
# Composition: Chair OWNS these parts
self.legs = [Leg("wood") for _ in range(4)]
self.seat = Seat("fabric")
self.arms = [Arm("wood") for _ in range(2)]
def __del__(self):
print("Chair deleted - all parts deleted with it")
# Usage
chair = Chair("red")
# When chair is deleted, all parts are automatically deleted
# Parts cannot exist without the chair
Key Characteristics
| Property | Details |
|---|---|
| Ownership | Container owns parts exclusively |
| Lifecycle | Parts die with container |
| Multiplicity | Fixed (usually 1:many or 1:1) |
| Independence | Parts cannot exist alone |
| Strength | Strongest relationship |
4οΈβ£ Aggregation (Weak HAS-A Relationship)
Definition: A whole-part relationship where parts can exist independently. The container only references the parts.
Notation: Line with unfilled (hollow) diamond on the container side
When to Use: - Parts can exist independently - Whole doesn't control lifecycle of parts - Looser coupling than composition
π Aggregation Diagram: University-Department Example
βββββββββββββββββββ
β University β
βββββββββββββββββββ€
β - name β
β - departments βββΌββββ
β - students βββΌββββ
βββββββββββββββββββ ββ
β ββ
/ \ ββ
/ \ ββ
ββββββββββββββββββββ βββ΄ββββββββββββββ
β Department β β Student β
ββββββββββββββββββββ€ βββββββββββββββββ€
β - name β β - name β
β - faculty β β - student_id β
ββββββββββββββββββββ€ βββββββββββββββββ€
β + getName() β β + getName() β
ββββββββββββββββββββ βββββββββββββββββ
Aggregation: Whole references Parts (not owns)
Multiplicity:
University HAS MANY Departments
University HAS MANY Students
Lifecycle: If University is deleted, Departments/Students continue to exist
Example Code
class Department:
def __init__(self, name):
self.name = name
def get_name(self):
return self.name
class Student:
def __init__(self, name, student_id):
self.name = name
self.student_id = student_id
class University:
def __init__(self, name):
self.name = name
self.departments = [] # Aggregation: references, not owns
self.students = []
def add_department(self, department):
self.departments.append(department)
def add_student(self, student):
self.students.append(student)
# Usage
dept = Department("Computer Science")
student = Student("Alice", 101)
university = University("MIT")
university.add_department(dept)
university.add_student(student)
# Even if university is deleted, department and student still exist
del university
print(dept.get_name()) # β Still works!
print(student.name) # β Still works!
Composition vs Aggregation
| Aspect | Composition | Aggregation |
|---|---|---|
| Notation | Filled diamond β | Hollow diamond β |
| Ownership | Container owns parts | Container references parts |
| Lifecycle | Parts die with container | Parts can outlive container |
| Independence | Parts cannot exist alone | Parts can exist independently |
| Strength | Strong | Weak |
| Example | Heart IS-PART-OF Body | Car HAS-A Engine (replaceable) |
π Relationships
Navigation Types
π One-Way Association
βββββββββββββββ βββββββββββββββ
β Driver βββββββββΆβ Vehicle β
βββββββββββββββ€ βββββββββββββββ€
β - name β β - licensePlateβ
βββββββββββββββ€ βββββββββββββββ€
β + drive() β β + start() β
βββββββββββββββ βββββββββββββββ
Navigation: Only Driver knows about Vehicle
Arrow direction shows navigation direction
π Two-Way Association (Bidirectional)
ββββββββββββββββ ββββββββββββββββ
β Person ββββββββββββββββββΆβ Company β
ββββββββββββββββ€ works for ββββββββββββββββ€
β - name β employs β - name β
β - company ββββΌββββββββββββββββ-β - employees β
ββββββββββββββββ€ ββββββββββββββββ€
β + getName() β β + getName() β
ββββββββββββββββ ββββββββββββββββ
Navigation: Both know about each other
Person knows Company
Company knows all its Employees
Code Example: Two-Way Association
class Company:
def __init__(self, name):
self.name = name
self.employees = []
class Person:
def __init__(self, name, company):
self.name = name
self.company = company # Reference to Company
self.company.employees.append(self) # Company knows Person
# Usage
company = Company("Google")
person = Person("John", company)
person2 = Person("Jane", company)
print(person.company.name) # PersonβCompany β
print(len(company.employees)) # CompanyβPersons β
Multiplicity
| Notation | Meaning | Example |
|---|---|---|
1 |
Exactly one | Each order has exactly 1 customer |
0..1 |
Zero or one | Optional relationship |
* or 0..* |
Zero or many | Order can have many items |
1..* |
One or many | Author has at least 1 book |
n |
Specific number | Deck has 52 cards |
π Multiplicity Examples
βββββββββββββββ 1 * ββββββββββββββββ
β Customer ββββββββββββββ Order β
βββββββββββββββ ββββββββββββββββ
One customer can have many orders
Each order belongs to one customer
ββββββββββββ 0..1 1..* βββββββββββββββ
β Teacher ββββββββββββββββββ Student β
ββββββββββββ βββββββββββββββ
A teacher may teach 1 to many students
A student must have 1 to many teachers
π Dependency
Definition: One class depends on another class for its implementation. The dependency exists when a class uses another class temporarily.
Notation: Dashed line with arrow pointing to the dependent class
When to Use: - Temporary relationships - A method receives an object as parameter - Weak coupling is desired - Usage is limited to specific operations
π Dependency Diagram
ββββββββββββββββββββ βββββββββββββββ
βRegistrationMgr β- - - - βΆβ Student β
ββββββββββββββββββββ€ uses βββββββββββββββ€
β - students[] β β - name β
ββββββββββββββββββββ€ βββββββββββββββ€
β+ register(s) β β + getName() β
β+ unregister(s) β βββββββββββββββ
ββββββββββββββββββββ
Dependency: Dashed line
RegistrationMgr depends on Student
(usually as method parameter or temporary usage)
Example Code
from typing import List
class Student:
def __init__(self, name, student_id):
self.name = name
self.student_id = student_id
class Course:
def __init__(self, course_id, title):
self.course_id = course_id
self.title = title
self.students: List[Student] = []
class RegistrationManager:
def register_student(self, student: Student, course: Course):
"""
Dependency: Uses Student object as parameter
Temporary usage - doesn't own the Student
"""
course.students.append(student)
print(f"{student.name} registered in {course.title}")
def generate_report(self, course: Course) -> str:
"""
Another dependency usage
"""
return f"Total students: {len(course.students)}"
# Usage
student = Student("Bob", 1)
course = Course(101, "Python")
manager = RegistrationManager()
# RegistrationManager depends on Student object
manager.register_student(student, course)
report = manager.generate_report(course)
Dependency vs Association
| Aspect | Dependency | Association |
|---|---|---|
| Lifetime | Temporary | Persistent |
| Notation | Dashed line | Solid line |
| Coupling | Weak | Strong |
| Usage | Method parameter | Object attribute |
| Example | sendEmail(person) | Student enrolled in Course |
π Real-World Examples
Example 1: E-Commerce System
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β E-COMMERCE SYSTEM β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
ββββββββββββββββ
β Customer β
ββββββββββββββββ€
β - name β
β - email β
β - address ββββΌββ
ββββββββββββββββ β
β³ β
β β
ββββββββ΄ββββββ β
β Premium β β
β Customer β β
ββββββββββββββ β
β
ββββββββββββββββββββββββββββββ€
β β
β βββββββββ΄βββββββββ
β β Address β
β ββββββββββββββββββ€
β β - street β
β β - city β
β β - country β
β ββββββββββββββββββ
β
β 1 *
βββββ΄ββββββββββββββββββββββ
β Order β
βββββββββββββββββββββββββββ€
β - orderId ββββ
β - items: List[Item] β β Composition
β - totalPrice β β Order OWNS items
βββββββββββββββββββββββββββ€ β
β + calculateTotal() β β
βββββββββββββββββββββββββββ β
β³ β
β β
ββββββββββ΄βββββββββββ β
β Item β β
βββββββββββββββββββββ€ β
β - itemId β β
β - quantity β β
β - product βββββββββΌβββββββββ
β - price β
βββββββββββββββββββββ€
β + getTotal() β
βββββββββββββββββββββ
β³
β
ββββββ΄βββββ
β Product β
βββββββββββ€
β - name β
β - price β
βββββββββββ
Relationships:
β Customer IS-A Entity (Inheritance to Premium Customer)
β Customer HAS-A Address (Aggregation)
β Customer HAS-MANY Orders (Aggregation)
β Order OWNS Items (Composition)
β Item references Product (Association)
Example 2: Library Management System
βββββββββββββββββββββββββββββββββββββββββββββββ
β LIBRARY MANAGEMENT SYSTEM β
βββββββββββββββββββββββββββββββββββββββββββββββ
ββββββββββββββββ
β Library β
ββββββββββββββββ€
β - name β
β - address β
β - books ββββββΌβββββββ
β - members ββββΌββββ β
ββββββββββββββββ β β
β³ β β
β β β
ββββββββ΄βββ βββββ΄βββ΄ββββββββ
β Member β β Book β
βββββββββββ€ ββββββββββββββββ€
β - id β β - isbn β
β - name β β - title β
β - books β β - author βββββΌβββ
β βββββββΌββ β - status β β
βββββββββββ€ β ββββββββββββββββ β
β β β
βββββββββββββββ β ββββββββββββ
β β β
ββββββ΄βββββββββ ββββββ΄βββββββββββ
β BorrowRecordβ β Author β
βββββββββββββββ€ βββββββββββββββββ€
β - dateOut β β - name β
β - dueDate β β - country β
β - dateReturnβ β - biography β
βββββββββββββββ βββββββββββββββββ
Relationships:
β Library HAS-MANY Books (Aggregation)
β Library HAS-MANY Members (Aggregation)
β Member BORROWS Books (Association)
β Member HAS-MANY BorrowRecords (Composition)
β Book written by Author (Association)
π― Interview Questions
Basic Level
Q1: What is the difference between association and aggregation?
Answer:
| Aspect | Association | Aggregation |
|---|---|---|
| Relationship | General relationship | Whole-Part relationship |
| Strength | Weaker | Slightly stronger |
| Notation | Simple line | Hollow diamond |
| Lifecycle | No specific binding | Parts can exist independently |
| Example | Student enrolls in Course | Library HAS Books |
Key Point: Aggregation is a special type of association with "HAS-A" semantics.
Q2: When would you use inheritance vs composition?
Answer:
Use Inheritance (IS-A) when: - There's a true "is-a" relationship (Dog IS-A Animal) - You want to share common behavior - You need polymorphism - The relationship is stable and fundamental
Use Composition (HAS-A) when: - You want flexible object creation - Relationships might change at runtime - You want to avoid deep hierarchies - Avoiding "Gorilla-Banana problem"
Example:
# β Good: Inheritance
class Animal:
def eat(self):
pass
class Dog(Animal): # Dog IS-A Animal
pass
# β Better: Composition for flexibility
class Dog:
def __init__(self):
self.behavior = Behavior() # Can change at runtime
def eat(self):
self.behavior.eat()
Q3: Explain the difference between composition and aggregation with an example.
Answer:
Composition (Strong relationship):
Car OWNS Engine
ββ If Car is destroyed β Engine is destroyed
ββ Parts cannot exist independently
ββ Solid diamond (β) notation
Aggregation (Weak relationship):
Library HAS Books
ββ If Library is destroyed β Books still exist
ββ Parts can exist independently
ββ Hollow diamond (β) notation
Real-world analogy: - Composition: Body composed of organs (organs die if body dies) - Aggregation: Team has players (players exist even if team dissolves)
Intermediate Level
Q4: What is the difference between dependency and association?
Answer:
| Aspect | Dependency | Association |
|---|---|---|
| Strength | Very Weak | Stronger |
| Notation | Dashed line | Solid line |
| Lifetime | Temporary | Persistent |
| Usage | Method parameter | Object attribute |
| Coupling | Loose | Tight |
| Example | sendEmail(user) | user.address |
Code Example:
# Dependency: Temporary usage
def send_notification(user: User, msg: Message): # Parameter
print(f"Sending to {user.name}")
# Association: Persistent relationship
class User:
def __init__(self):
self.email = Email() # Persistent attribute
Q5: How would you model a library management system with class diagrams?
Answer:
ββββββββββββββββ
β Library β
ββββββββββββββββ€
β - name β
β - books ββββββΌββββ
β - members ββββ€ β
ββββββββββββββββ β
β³ β
ββββββββ΄βββββββ β
βMember β β
βββββββββββββββ€ β
β - name β β
β - memberId β β
β - borrowedβββΌβββ β
βββββββββββββββ β β
β β
ββββββββββββββββββββββββββββββΌββ
β β
β ββββββββββββββ΄βββ
β β Book β
β βββββββββββββββββ€
β β - isbn β
β β - title β
β β - author ββββ β
β βββββββββββββββββ€
β β + getDetails()β
β βββββββββββββββββ
β β³
β β
ββββββββββββββββ¬ββββββββββ
β
βββββββββββββββ΄βββββββββββ
β Author β
ββββββββββββββββββββββββββ€
β - name β
β - country β
ββββββββββββββββββββββββββ
Relationships:
β Library HAS-MANY Books (Aggregation) - Books exist independently
β Library HAS-MANY Members (Aggregation) - Members exist independently
β Member BORROWED Books (Association with multiplicity)
β Book written by Author (Association)
Q6: Explain the Liskov Substitution Principle with inheritance example.
Answer:
LSP: Objects of a superclass should be replaceable with objects of its subclasses without breaking the application.
β Good Example:
class Bird:
def fly(self):
return "Flying"
class Eagle(Bird):
def fly(self):
return "Soaring high"
class Sparrow(Bird):
def fly(self):
return "Flying fast"
# Can substitute any Bird with its subclass
birds: List[Bird] = [Eagle(), Sparrow()]
for bird in birds:
print(bird.fly()) # Works correctly
β Bad Example:
class Bird:
def fly(self):
return "Flying"
class Penguin(Bird):
def fly(self):
raise Exception("Penguins can't fly!") # Violates LSP!
# This breaks the contract
penguin: Bird = Penguin()
penguin.fly() # Unexpected error
Solution:
class Bird:
pass
class FlyingBird(Bird):
def fly(self):
pass
class SwimmingBird(Bird):
def swim(self):
pass
class Penguin(SwimmingBird): # Correct inheritance
def swim(self):
return "Swimming"
Advanced Level
Q7: Design a class diagram for a ride-sharing application (like Uber).
Answer:
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β RIDE-SHARING APPLICATION β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
ββββββββββββββββββββ
β User β
ββββββββββββββββββββ€
β - userId β
β - name β
β - phone β
β - ratings β
β - location βββββββΌβββ
ββββββββββ¬ββββββββββ β
β³ β
ββββββββββββββββββββββΌβββββββββββββ€
β β β
β βββββββββ΄ββββ βββββ΄βββββββ
β β Passenger β β Driver β
β β β ββββββββββββ€
β βββββββββββββ β - vehicleβ
β β -license β
β ββββββ¬ββββββ
β β
β ββββββββββ΄βββββββ
β β Vehicle β
β βββββββββββββββββ€
β β - licensePlateβ
β β - model β
β β - capacity β
β βββββββββββββββββ
β
β 1 *
βββββ΄βββββββββββββββββββββββ
β Ride β
ββββββββββββββββββββββββββββ€
β - rideId β
β - pickupLocation βββββ β
β - dropoffLocation ββββΌββ β
β - startTime β β β
β - endTime β β β
β - fare β β β
β - status β β β
β - driver βββββββββββββΌββ β
β - passenger ββββββββββ β
ββββββββββββββββββββββββββββ€
β + calculateFare() β
β + updateStatus() β
ββββββββββββββββββββββββββββ
Relationships:
β Passenger/Driver IS-A User (Inheritance)
β Driver HAS-A Vehicle (Composition) - Driver must have vehicle
β Ride HAS-MANY Locations (Composition)
β Ride references Driver & Passenger (Association)
β Ride tracks pickupLocation & dropoffLocation (Dependency)
Q8: What are the advantages and disadvantages of deep inheritance hierarchies?
Answer:
Disadvantages of Deep Hierarchies: - β Hard to understand and maintain - β Fragile base class problem - β Difficult to add new variations - β Risk of misusing inherited methods - β Violates Single Responsibility Principle
Advantages: - β Code reuse at multiple levels - β Clear hierarchical organization (sometimes) - β Enforces consistency
Best Practice:
Keep hierarchies shallow (max 3 levels)
Level 0: Base class (Animal)
Level 1: Intermediate (Mammal)
Level 2: Concrete (Dog) β Stop here!
Better Approach - Composition:
# Instead of: Dog -> Animal -> LivingBeing -> ...
# Use composition:
class Dog:
def __init__(self):
self.behavior = AnimalBehavior()
self.movement = FourLeggedMovement()
self.diet = CarnivoreeDiet()
π Summary Table
| Concept | Symbol | Strength | When to Use |
|---|---|---|---|
| Inheritance | β³ | Strong | IS-A relationship |
| Composition | β | Strong | Whole owns parts |
| Aggregation | β | Weak | Whole references parts |
| Association | β | Medium | Objects interact |
| Dependency | - - -βΊ | Weak | Temporary usage |
π Quick Decision Tree
Do classes have an IS-A relationship?
ββ YES β Use Inheritance (β³)
ββ NO β Continue to next question
Does one class own/create the other?
ββ YES β Use Composition (β)
ββ NO β Continue to next question
Can parts exist without the whole?
ββ YES β Use Aggregation (β)
ββ NO β Use Association (β)
Is the relationship temporary/parameter-based?
ββ YES β Use Dependency (- - -βΊ)
ββ NO β Use Association (β)
π References & Further Reading
- UML Specification by OMG
- "Design Patterns" by Gang of Four
- "Head First Design Patterns"
- "Refactoring" by Martin Fowler
- "Clean Architecture" by Robert C. Martin
- "Object-Oriented Design in Java" by Stephen Cole