Home › Low-Level Design › UML and Class Diagrams
U

UML and Class Diagrams

A class diagram is the map you draw before you write a single line of code. In a 35-to-45-minute LLD interview it is how you show what is in your head without making the interviewer read 200 lines of Java off a whiteboard.

Low-Level DesignEasy9 min read

I have sat on both sides of this table, and the pattern is consistent:

If you remember five things

The whole page in one glance. Everything below is the defense of these five calls.

  1. Boxes are nouns, arrows are relationships. Name the objects, then draw how each pair relates. A diagram with no arrows tells the interviewer nothing.
  2. Five arrows, not fifty. Association, aggregation, composition, inheritance, realization. Learn these cold and you can model any LLD prompt.
  3. Lifetime decides has-a. Composition means the part dies with the whole. Aggregation means the part outlives it. That is the real distinction, not the diamond color.
  4. Program to interfaces where it matters. The realization arrow is where Dependency Inversion lives and where Strategy and Factory slot in. This is the senior signal.
  5. Draw it first, then talk while you draw. It is your opening move in the first five minutes, and the reasoning you say out loud scores higher than the picture.

1The problem it solves#

Pin down what the pieces are and how they connect before you argue about method signatures. The diagram is the shared language that makes that possible.

The situation you are handed.

  • You get asked to design a parking lot, a ride-sharing system, or a vending machine.
  • You have 35 minutes, and maybe 5 go to clarifying requirements.
  • You need to agree on the objects and their connections before debating whether withdraw() returns a boolean or throws.

Why jumping straight to code hurts you.

  • You lose the forest for the trees: deep in a withdraw() method while the interviewer wonders why there is no Account class at all.
  • You cannot change your mind cheaply. Moving a box takes two seconds; refactoring whiteboard code at minute 25 burns the time you needed for the hard part.

What the diagram buys you.

  • It is compact, visual, and forces the big decisions out loud: what are the objects, what do they own, who talks to whom.
  • Get that right and the code almost writes itself.
The one job of the diagram

It is a contract you and the interviewer agree on before writing code. Its entire value is making structural decisions cheap to change and visible to both of you. The moment you stop updating it, it stops being a contract and becomes decoration.

2The idea (mental model)#

Think of a class diagram as a set of boxes connected by arrows. That is the entire model.

Each box is a class, in three stacked sections.

  • The name on top.
  • The data it holds (fields) in the middle.
  • The things it can do (methods) on the bottom.

The arrows are the interesting part. They answer one question: when object A needs to know about object B, what kind of relationship is that?

  • Is B a part of A?
  • Does A just borrow a reference to B?
  • Is A a specialized kind of B?

So the whole technique reduces to two moves.

  • Boxes for the nouns.
  • Arrows for how the nouns relate.
  • Name the nouns, draw the right arrow between each pair, and you have a class diagram.

One note on visibility symbols, because they come up.

  • + means public, - means private, # means protected.
  • I keep fields private (-) and methods public (+) unless there is a reason not to.
  • Nobody fails you over a visibility marker, but it signals you think about encapsulation, which is the start of the Single Responsibility and open-closed thinking the interviewer is watching for.

3Structure#

The relationships are where candidates either look sharp or look shaky. There are really only five, and they sit on a spectrum from "loosely knows about" to "literally made of."

  • Association (-->): A uses B. A holds a reference, but B can live on its own. A Driver is associated with a Car.
  • Aggregation (o--): A "has" B, and B can exist without A. A Team has Player objects, but if the team dissolves the players still exist. Hollow diamond.
  • Composition (*--): A owns B, and B dies when A dies. An Order is composed of OrderItems. Delete the order and those line items mean nothing. Filled diamond.
  • Inheritance (<|--): B is a kind of A. A SavingsAccount is an Account. Hollow triangle pointing at the parent.
  • Realization or implements (..|>): B implements interface A. A CreditCardPayment realizes a PaymentMethod interface.

The honest truth about aggregation versus composition.

  • In interviews the line gets fuzzy, and nobody quibbles if you call a has-a relationship by either name.
  • What matters is knowing the difference in lifetime.
  • Composition means shared death. Aggregation means independent life.

Here is a small banking model that uses most of these:

classDiagram class Account { -String id -double balance +deposit(amount) void +withdraw(amount) bool } class SavingsAccount { -double interestRate +applyInterest() void } class CheckingAccount { -double overdraftLimit } class Customer { -String name +openAccount() Account } class Transaction { -double amount -String type } class PaymentMethod { +pay(amount) bool } class CreditCardPayment { +pay(amount) bool } Account <|-- SavingsAccount Account <|-- CheckingAccount Customer o-- Account Account *-- Transaction Customer --> PaymentMethod PaymentMethod <|.. CreditCardPayment
A banking model using four of the five arrows. Aggregation (hollow diamond) from Customer to Account, composition (filled diamond) from Account to Transaction, inheritance to the two account subtypes, and realization from CreditCardPayment to the PaymentMethod interface.

Read it out loud the way you would at the whiteboard.

  • A Customer has Accounts (aggregation, because closing one account does not delete the customer).
  • Each Account owns its Transactions (composition, because a transaction without its account is garbage).
  • SavingsAccount and CheckingAccount are kinds of Account.
  • CreditCardPayment implements the PaymentMethod interface.

That last arrow is not decoration.

  • Programming to the PaymentMethod interface instead of a concrete card class is the Dependency Inversion Principle.
  • It is exactly where the Strategy pattern slots in when you want to swap card, wallet, and UPI at runtime.
Pause before you read on: a `Playlist` holds `Song`s. Deleting a playlist must not delete the songs, since other playlists still use them. Aggregation or composition, and which diamond?
Reveal the answer
Aggregation, hollow diamond (`Playlist o-- Song`). The songs outlive any single playlist, so they have independent life. Composition would be wrong here: it says the songs die with the playlist, which would nuke a track the moment one playlist referencing it is removed. The lifetime question ("does the part die with the whole?") picks the arrow every time.

4Implementation in Java#

Each arrow becomes a specific Java construct, which is why a clean diagram translates straight into code. Here is the banking model turned into just enough Java to make the relationships concrete.

// Inheritance: SavingsAccount <|-- Account
abstract class Account {
    private String id;
    private double balance;

    public void deposit(double amount) {
        balance += amount;
    }

    public boolean withdraw(double amount) {
        if (amount > balance) return false;
        balance -= amount;
        return true;
    }

    public double getBalance() { return balance; }
}

class SavingsAccount extends Account {
    private double interestRate;

    public void applyInterest() {
        deposit(getBalance() * interestRate);
    }
}

// Composition: Account *-- Transaction
// The account creates and owns its transactions.
class Transaction {
    private final double amount;
    private final String type;

    Transaction(double amount, String type) {
        this.amount = amount;
        this.type = type;
    }
}

// Aggregation: Customer o-- Account
// Accounts are passed in from outside; the customer does not create them.
class Customer {
    private String name;
    private final List<Account> accounts = new ArrayList<>();

    public void addAccount(Account account) {
        accounts.add(account);   // reference held, not owned
    }
}

// Realization: CreditCardPayment ..|> PaymentMethod
interface PaymentMethod {
    boolean pay(double amount);
}

class CreditCardPayment implements PaymentMethod {
    @Override
    public boolean pay(double amount) {
        // charge the card
        return true;
    }
}

The tell for composition versus aggregation lives in the code, not the diagram.

  • Composition: the owner creates the part. An Account would new its own Transaction.
  • Aggregation: the part is handed in from outside, as in addAccount(Account account).
  • That is the exact distinction the diamond notation captures, and it is worth saying out loud in the interview.

The aggregation version is also looser coupling, which earns points on its own.

  • Customer depends on the Account type, not on constructing it.
  • That keeps the class testable: you can hand in a stub instead of a real account.
Say the mapping out loud

When you draw a filled diamond, follow it with "so the owner news this up in its constructor," and for a hollow diamond, "so this gets passed in." Narrating the arrow-to-code mapping proves the diagram is not cargo-culted notation. It is the single cheapest way to sound like someone who has actually shipped this code.

5A real-world example#

Take a food delivery app, the kind of thing you might actually get asked to design. The nouns fall out quickly, and the arrows follow from one question about ownership.

The nouns.

  • User, Restaurant, MenuItem, Cart, Order, Payment, DeliveryAgent.

The arrows, decided by "does the part die with the whole?"

  • A Restaurant owns its MenuItems. If the restaurant leaves the platform, those menu items go with it. Composition.
  • A Cart references MenuItems. Deleting your cart does not delete the restaurant's dishes. Association.
  • An Order owns its OrderLines (the frozen snapshot of what you bought at what price). Composition, because an order line outside its order is meaningless.
  • An Order references one Payment and one DeliveryAgent. The agent exists whether or not this order does. Association.

Why this maps straight onto real backend models.

  • Composition relationships usually become owned child tables with cascade-delete.
  • Associations become foreign keys to rows that live independently.
  • Drawing these four arrows correctly tells me you understand data ownership, and that is most of LLD right there.

The same shape shows up everywhere once you see it.

  • ParkingLot o-- ParkingSpot, Playlist o-- Song, Document *-- Paragraph.
  • Learn to ask "does the part die with the whole?" and the arrow picks itself.

6When to use it, and when not to#

The class diagram is your default opening move, but it answers only one kind of question. Know the boundary.

Use it when the problem is about structure.

  • What objects exist, what they contain, how they relate.
  • Almost every LLD interview is exactly this.
  • Draw it in the first five minutes, right after you nail down requirements.

Do not lean on it when the question is about behavior over time.

  • "What happens, step by step, when a user checks out?" is a sequence question, not a structure question.
  • A class diagram shows a frozen snapshot; it cannot show order of events.
  • For that, reach for a sequence diagram:
sequenceDiagram participant U as User participant C as Cart participant O as OrderService participant P as PaymentGateway U->>C: checkout() C->>O: createOrder(cartItems) O->>P: charge(amount) P-->>O: paymentConfirmed O-->>U: orderPlaced(orderId)
A sequence diagram for checkout. It shows order of events (what calls what, and when), which the class diagram structurally cannot. Reach for this the moment the interviewer asks about a flow rather than a structure.

Also skip the full UML ceremony when a quick sketch does the job.

  • You do not need multiplicities, stereotypes, and perfectly drawn diamonds on a whiteboard.
  • Clear boxes and correct arrows beat a textbook-perfect diagram that took fifteen minutes.
  • Fifteen minutes is nearly half your budget.

7Common mistakes#

These are the ones I see cost real candidates. Each maps to a principle the interviewer is quietly scoring.

  • Fields and methods everywhere, no arrows. The most common one. Five beautiful boxes, never connected. The arrows are the design; a diagram with no relationships tells me nothing.
  • Inheritance for code reuse. Reaching for extends just to share a couple of methods. Inheritance means "is-a." If AdminUser is genuinely a kind of User, fine. If you are inheriting to grab a helper, use composition. This is the single most over-used arrow, and "favor composition over inheritance" is the exact phrase the interviewer wants to hear. Deep inheritance trees also break the Liskov Substitution Principle fast.
  • God class. One box with twenty fields and fifteen methods. That is a smell, not a design. It usually means you skipped asking what the real nouns are, and it violates Single Responsibility on its face.
  • Confusing composition with aggregation and then sweating it. Know the lifetime difference, say which one you mean, and move on. I have never failed a candidate over a diamond color. I have failed them for not knowing an Order owns its line items.
  • Drawing the diagram and then ignoring it. If your code and your diagram disagree by minute 25, you have lost the plot. The diagram is a living contract. Update it when you change your mind.
The misuse that actually fails you

Using inheritance as a shortcut for sharing code. It feels efficient and it is the fastest way to signal that you do not reach for composition by default. When you catch yourself typing extends, say the words "is X truly a kind of Y?" out loud. If the honest answer is "no, I just want its helper() method," you want a field, not a parent.

8Where it shows up in interviews#

Every structural LLD question opens here. "Design a parking lot," "design a library management system," "design an elevator," "design a chess game."

The expected first move is always the same.

  • Clarify requirements, then draw the class diagram.
  • This is the Easy-rated opener at companies like Amazon, Uber, and Atlassian.
  • It gates the rest of the loop: botch the structure and you never reach the patterns that earn the senior signal.

What the interviewer is actually scoring.

  • Did you find the right classes? (Good noun extraction.)
  • Are your relationships correct? (Aggregation versus composition versus inheritance.)
  • Did you program to interfaces where it matters? (That is where Strategy, Factory, and Dependency Inversion start.)
  • Can you walk the diagram and explain a flow? (This is where a sequence diagram earns points.)

My one piece of advice: talk while you draw.

  • "I will make Account abstract because we never instantiate a plain account."
  • "Customer aggregates accounts, hollow diamond, because accounts outlive any single session."
  • That narration is worth more than the drawing itself. It shows how you reason, and reasoning is the thing I am hiring for.
Follow-ups the interviewer will ask (and your answers)
"You drew inheritance from `PremiumUser` to `User` just to share the notification code. Defend that."
I would not defend it, I would fix it. Inheritance means `PremiumUser` is-a `User` for all purposes, and if I only wanted the notification helper, that is reuse, not an is-a relationship. I would pull the notification logic into its own collaborator and have both user types hold a reference to it (composition). That keeps me clear of the Liskov trap where a subtype has to override away behavior it does not actually want.
"When does aggregation become composition in your model, concretely?"
It is a lifetime call. If the part is created by the owner and is meaningless once the owner is gone, that is composition: an `Order` news its own `OrderLine`s, and a line item without its order is garbage. If the part is handed in and survives independently, that is aggregation: a `Customer` is given `Account`s it did not construct, and closing the customer session does not delete them. In code the tell is who calls `new`.
"The interviewer asks what happens during checkout step by step. Is your class diagram enough?"
No, and I would say so. A class diagram is a frozen structural snapshot; it cannot express order of events. Checkout is a behavior-over-time question, so I switch to a sequence diagram showing User to Cart to OrderService to PaymentGateway and back. Using the right diagram for the right question is itself part of the signal.
"Your `Order` class has grown to eighteen fields and twelve methods. Problem?"
Yes, that is a God class and it violates Single Responsibility. It usually means I merged several nouns into one box. I would split it: pricing logic into a `PricingPolicy`, payment into a `Payment` collaborator, line items into their owned `OrderLine`s. The arrows I add while splitting are the design improving, which is the opposite of a problem.
"Where do design patterns enter this diagram?"
At the realization arrows. The moment I program to an interface like `PaymentMethod` instead of a concrete `CreditCardPayment`, I have the seam for Strategy (swap payment algorithms at runtime) and Factory (centralize which concrete type gets built). That interface boundary is Dependency Inversion in practice, and it is exactly the senior signal the loop is checking for after the structure is right.

What you can now explain in the room

  • Why you draw a class diagram first and what decisions it forces out loud before any code.
  • The five relationships and the exact Java construct each one maps to.
  • How lifetime ("does the part die with the whole?") decides aggregation versus composition, in both notation and code.
  • Why programming to an interface is where Dependency Inversion, Strategy, and Factory begin.
  • When to switch to a sequence diagram instead, and why structure cannot show order of events.
  • The classic misuse (inheritance for code reuse) and how to catch and fix it with composition.

Next, read the guides on the Strategy and Factory patterns, and the full Parking Lot LLD walkthrough, to see these arrows turn into real designs.

Get a prep plan built around your UML and Class Diagrams interview

Tell us the role and your interview date. We will send back a dated, day by day plan. Free.

Thanks. Check your inbox, your UML and Class Diagrams prep plan is on the way.