Skip to content
Low Level Design Mastery Logo
LowLevelDesign Mastery

Class Diagrams

Master class diagrams - visualize your design and communicate effectively in LLD interviews!

Class diagrams are the visual representation of your design. They help you:

  • Communicate your design to interviewers
  • Visualize relationships between classes
  • Identify design issues early
  • Plan implementation
Diagram

Class diagrams show:

A class in a diagram shows:

  • Class Name - At the top
  • Attributes - Properties/fields (middle section)
  • Methods - Operations (bottom section)
Diagram
  • + Public - Accessible from anywhere
  • - Private - Only accessible within class
  • # Protected - Accessible within class and subclasses
  • ~ Package - Accessible within package

  1. Inheritance (is-a) - Generalization
  2. Composition (has-a, owns) - Strong ownership
  3. Aggregation (has-a, uses) - Weak ownership
  4. Association (uses) - Reference/usage
  5. Dependency (depends on) - Temporary usage
Diagram

Inheritance represents an “is-a” relationship. A subclass is a type of superclass.

Example: Car is a Vehicle

  • Solid line with hollow triangle pointing to parent
  • Arrow: Child → Parent
classDiagram
    class Vehicle {
        <<abstract>>
        -String licensePlate
        -VehicleType vehicleType
        +getVehicleType() VehicleType
    }
    
    class Car {
        +getVehicleType() VehicleType
    }
    
    class Motorcycle {
        +getVehicleType() VehicleType
    }
    
    class Truck {
        +getVehicleType() VehicleType
    }
    
    Vehicle <|-- Car : extends
    Vehicle <|-- Motorcycle : extends
    Vehicle <|-- Truck : extends
Diagram

Use when:

  • Subclass is a type of superclass
  • Subclass shares common behavior
  • You want polymorphism

Don’t use when:

  • Just sharing code (use composition)
  • Relationship is “has-a” not “is-a”

Composition represents a “has-a” relationship with strong ownership. The whole owns the parts, and parts cannot exist without the whole.

Example: ParkingLot has ParkingSpots (spots don’t exist without the lot)

  • Solid line with filled diamond on the whole side
  • Arrow: Part → Whole
  • Multiplicity: 1 to many
classDiagram
    class ParkingLot {
        -List~ParkingSpot~ spots
        -int capacity
        +parkVehicle(Vehicle) Ticket
        +unparkVehicle(Ticket) Payment
    }
    
    class ParkingSpot {
        -String spotId
        -VehicleType spotType
        -boolean isOccupied
        +parkVehicle(Vehicle) void
        +unparkVehicle() Vehicle
    }
    
    ParkingLot "1" *-- "many" ParkingSpot : contains
Diagram

Use when:

  • Whole owns parts
  • Parts cannot exist without whole
  • Lifecycle is tied together
  • Strong relationship

Example: Car has Engine (engine doesn’t exist without car)


Aggregation represents a “has-a” relationship with weak ownership. The whole uses the parts, but parts can exist independently.

Example: Team has Players (players exist without team)

  • Solid line with hollow diamond on the whole side
  • Arrow: Part → Whole
  • Multiplicity: 1 to many
classDiagram
    class Team {
        -String teamName
        -List~Player~ players
        +addPlayer(Player) void
        +removePlayer(Player) void
    }
    
    class Player {
        -String playerId
        -String name
        +getName() String
    }
    
    Team "1" o-- "many" Player : has
Diagram

Use when:

  • Whole uses parts
  • Parts can exist independently
  • Lifecycle is independent
  • Weak relationship

Example: Library has Books (books exist without library)

AspectCompositionAggregation
OwnershipStrongWeak
LifecycleTied togetherIndependent
ExampleCar-EngineTeam-Player
DiamondFilledHollow

Association represents a “uses” relationship. One class references or uses another class.

Example: Ticket references Vehicle

  • Solid line with arrow (optional)
  • Arrow: Source → Target
  • Can have multiplicity
classDiagram
    class Ticket {
        -String ticketId
        -DateTime entryTime
        +calculateDuration() Duration
    }
    
    class Vehicle {
        -String licensePlate
        -VehicleType vehicleType
        +getVehicleType() VehicleType
    }
    
    class ParkingSpot {
        -String spotId
        -boolean isOccupied
    }
    
    Ticket --> Vehicle : references
    Ticket --> ParkingSpot : references
Diagram

Use when:

  • One class uses another
  • Reference relationship
  • Not ownership
  • Temporary or optional

Example: Order references Customer (order uses customer info)


Dependency represents a temporary “depends on” relationship. One class depends on another for a specific operation.

Example: Method parameter, return type, local variable

  • Dashed line with arrow
  • Arrow: Dependent → Dependency
classDiagram
    class ParkingLotService {
        +parkVehicle(Vehicle) Ticket
        +unparkVehicle(Ticket) Payment
    }
    
    class ParkingSpotRepository {
        +findAvailableSpot(VehicleType) ParkingSpot
        +save(ParkingSpot) void
    }
    
    ParkingLotService ..> ParkingSpotRepository : uses
Diagram

Use when:

  • Temporary relationship
  • Method parameter
  • Return type
  • Local variable usage

classDiagram
    class ParkingLot {
        -List~ParkingSpot~ spots
        -int capacity
        +parkVehicle(Vehicle) Ticket
        +unparkVehicle(Ticket) Payment
        -findAvailableSpot(VehicleType) ParkingSpot
    }
    
    class ParkingSpot {
        -String spotId
        -VehicleType spotType
        -boolean isOccupied
        -Vehicle vehicle
        +parkVehicle(Vehicle) void
        +unparkVehicle() Vehicle
        +isAvailable() boolean
    }
    
    class Vehicle {
        <<abstract>>
        -String licensePlate
        -VehicleType vehicleType
        +getVehicleType() VehicleType
    }
    
    class Car {
        +getVehicleType() VehicleType
    }
    
    class Motorcycle {
        +getVehicleType() VehicleType
    }
    
    class Ticket {
        -String ticketId
        -DateTime entryTime
        +calculateDuration() Duration
    }
    
    class Payment {
        -String paymentId
        -float amount
        -DateTime paymentTime
        +processPayment() boolean
    }
    
    ParkingLot "1" *-- "many" ParkingSpot : contains
    ParkingLot --> Ticket : creates
    ParkingLot --> Payment : creates
    ParkingSpot --> Vehicle : contains
    Ticket --> Vehicle : references
    Ticket --> ParkingSpot : references
    Payment --> Ticket : references
    Vehicle <|-- Car : extends
    Vehicle <|-- Motorcycle : extends
Diagram
RelationshipTypeExample
ParkingLot → ParkingSpotCompositionParkingLot has ParkingSpots (owns)
Vehicle → CarInheritanceCar is a Vehicle
Ticket → VehicleAssociationTicket references Vehicle
Payment → TicketAssociationPayment references Ticket
ParkingLot → TicketDependencyParkingLot creates Ticket

Multiplicity shows how many instances participate in a relationship.

  • 1 - Exactly one
  • 0..1 - Zero or one (optional)
  • 1..* - One or more
  • * or 0..* - Zero or more (many)
  • n..m - Between n and m
classDiagram
    class ParkingLot {
        -List~ParkingSpot~ spots
    }
    
    class ParkingSpot {
        -Vehicle vehicle
    }
    
    class Ticket {
        -Vehicle vehicle
        -ParkingSpot spot
    }
    
    ParkingLot "1" *-- "many" ParkingSpot : contains
    ParkingSpot "1" --> "0..1" Vehicle : contains
    Ticket "1" --> "1" Vehicle : references
    Ticket "1" --> "1" ParkingSpot : references
Diagram

Interfaces define contracts that classes implement.

UML Notation: <<interface>> or I prefix

classDiagram
    class PaymentProcessor {
        <<interface>>
        +processPayment(amount, method) boolean
        +refundPayment(paymentId) boolean
    }
    
    class StripeProcessor {
        +processPayment(amount, method) boolean
        +refundPayment(paymentId) boolean
    }
    
    class PayPalProcessor {
        +processPayment(amount, method) boolean
        +refundPayment(paymentId) boolean
    }
    
    PaymentProcessor <|.. StripeProcessor : implements
    PaymentProcessor <|.. PayPalProcessor : implements

Abstract classes provide partial implementation.

UML Notation: <<abstract>> or italic name

classDiagram
    class Vehicle {
        <<abstract>>
        -String licensePlate
        +getVehicleType() VehicleType
        +calculateParkingFee() float
    }
    
    class Car {
        +getVehicleType() VehicleType
        +calculateParkingFee() float
    }
    
    Vehicle <|-- Car : extends

Use clear names - Descriptive class and method names
Show key relationships - Don’t show everything, focus on important ones
Use proper notation - Follow UML standards
Group related classes - Organize diagram logically
Show multiplicities - When important
Use interfaces - For abstraction

Don’t show everything - Focus on important relationships
Don’t use wrong relationships - Understand composition vs aggregation
Don’t make it too complex - Keep it readable
Don’t forget access modifiers - Show visibility
Don’t mix concepts - Keep layers separate

Diagram

Class diagrams visualize your design
Inheritance - “is-a” relationship (solid line, hollow triangle)
Composition - “has-a” with ownership (filled diamond)
Aggregation - “has-a” without ownership (hollow diamond)
Association - “uses” relationship (solid line)
Dependency - “depends on” (dashed line)
Multiplicity - Shows quantity in relationships
Interfaces - Define contracts

RelationshipNotationWhen to Use
InheritanceSolid line, hollow triangle”is-a” relationship
CompositionSolid line, filled diamondStrong ownership
AggregationSolid line, hollow diamondWeak ownership
AssociationSolid line, arrowReference/usage
DependencyDashed line, arrowTemporary dependency
Diagram

Now that you’ve mastered class diagrams, let’s learn how to define contracts and APIs:

Next: Contract and API Definitions →

This next guide will teach you how to define clear interfaces, method signatures, and API contracts for your design!