When a bus depot in the city is closed, the buses are not scrapped. They are simply driven to another depot and keep running their routes the next morning. The depot was a group of buses, a "whole" made of "parts", but it never owned the buses' lives. That kind of relationship has a name in object-oriented design: aggregation.

Aggregation = a "has-a" relationship in which one object (the whole) groups other objects (the parts), but the parts are created outside it and can live on after the whole is gone.

Real-world analogy: A WhatsApp group has members. If the admin deletes the group, the members are still on WhatsApp, still in their other groups, and still in your contacts. The group only gathered them together. Compare that with a message inside the group: delete the group and its messages are gone with it. The members are aggregated; the messages are composed.

1. What Is Aggregation?

Aggregation is a special kind of association. It adds a clear whole-part meaning to the link, but without ownership of the parts' lifecycle. Its characteristics:

  • Whole and parts. One class is clearly the container (Depot, StudyGroup, Event) and the other is what it contains (Bus, Student, Speaker).
  • The parts are created outside the whole and handed to it.
  • The parts survive the whole. Removing or deleting the whole does not delete the parts.
  • The parts can be shared. The same student can be in two study groups at once.
  • The parts can move from one whole to another.

It sits in the middle of the three "has-a" style relationships:

AssociationAggregationComposition
MeaningA knows or uses BA is a whole made of B partsA owns B parts
Who creates B?Someone elseSomeone elseA itself
B after A is destroyedStill existsStill existsDestroyed with A
Can B be shared?YesYesNo
UMLSolid lineHollow diamond at the wholeFilled diamond at the whole
ExampleOrder and RestaurantDepot and BusOrder and OrderLine

2. UML Notation

Aggregation is drawn as a line with a hollow (empty) diamond on the side of the whole. Multiplicity works the same way as for association.

Read it as: "one Depot parks any number of Buses, and the buses do not depend on the depot to exist."

3. A Basic Example: Depot and Buses

In this example the buses are created first. Depots are created afterwards, and buses are added to them. When the Dilsukhnagar depot is closed, its buses move to Uppal.

Output

Dilsukhnagar depot: TS10Z1001 (218), TS10Z1002 (10H)
Uppal depot: TS10Z1003 (290U)
Dilsukhnagar depot closed.
Uppal depot: TS10Z1003 (290U), TS10Z1001 (218), TS10Z1002 (10H)
TS10Z1001 still runs route 218

What makes this aggregation and not composition:

  • Depot never creates a Bus. addBus() receives a bus that already exists.
  • Destroying the depot does not destroy the buses. In C++ the depot holds non-owning pointers and its destructor does nothing to the buses. In Java, Python and JavaScript the buses are still referenced from main, so the garbage collector keeps them.
  • The same bus objects move to another depot. Nothing is copied; the route numbers are still the same.

4. Shared Parts

Because the whole does not own its parts, one part can belong to several wholes at the same time. On a coding practice site, Lakshmi can be in both the "DSA Circle" and the "SQL Squad" study groups. Both groups hold a reference to the same Student object.

Output

DSA Circle: Lakshmi, Farhan | total XP 200
SQL Squad: Lakshmi, Deepa | total XP 215
Lakshmi solves a hard problem: +30 XP
DSA Circle total XP: 230
SQL Squad total XP: 245
DSA Circle disbanded.
SQL Squad: Lakshmi, Deepa | total XP 245
Lakshmi still has 150 XP
  • When Lakshmi earns 30 XP, both groups see it immediately, because they point to one object, not two copies.
  • Disbanding the DSA Circle removes the group, but Lakshmi stays in the SQL Squad with all her XP.
  • This sharing is exactly what you want for real-world entities: there is one Lakshmi in the system, so there should be one Student object.

The flip side: because the part is shared, any whole can change it, and the change is visible everywhere. If a whole should not be able to change its parts, give it a read-only view (see section 6).

5. Aggregation vs Composition in One Example

The quickest way to understand aggregation is to see it next to composition. In a stationery shop:

  • The Catalog aggregates Products. Products exist on their own, and many orders refer to them.
  • An Order is composed of OrderLines. Each line is created by the order, belongs to exactly one order, and means nothing without it.
  • Each OrderLine simply refers to a Product (an association).

Output

Order #7: 2 x Notebook = Rs.120, 1 x Pen Pack = Rs.85 | total Rs.205
Order #7 cancelled: its 2 lines go away with it
Catalog still has: Notebook (Rs.60), Pen Pack (Rs.85), Stapler (Rs.150)
  • OrderLine is created only inside Order.addItem() and is private to the order (a nested or private class). That is composition: when the order goes, its lines go too. In C++ the lines are stored by value inside the order, so the order's destructor destroys them.
  • Products are created once and added to the catalog. Cancelling the order does not touch them, and the catalog still lists all three. That is aggregation.

A simple test: "If I delete the whole, should the part be deleted too?" If yes, it is composition. If no, and the part is still part of a whole, it is aggregation.

6. Designing Aggregation Well

Here is a fuller example: a tech event that brings together a venue and a set of speakers. The event is cancelled, and a speaker is booked for another event.

Output

DevFest Hyderabad @ HICC Hall 3 (500 seats)
  - Ravi: Spring Boot
  - Neha: System Design
DevFest Hyderabad is cancelled.
Java Meetup @ T-Hub (120 seats)
  - Ravi: Spring Boot
Speakers still registered: Ravi, Neha

The design choices that make this a good aggregation:

  • Inject the parts. The venue is passed into the constructor and speakers are added with addSpeaker(). The event never calls new Speaker(...) itself. This keeps Event loosely coupled and easy to test with fake speakers.
  • Do not hand out the internal list. getSpeakers() returns a read-only view (Java Collections.unmodifiableList, a C++ const reference, a Python tuple, a frozen JavaScript array). Callers can read the lineup but cannot add or remove speakers behind the event's back.
  • Never delete the parts when the whole is destroyed. In C++ that means non-owning pointers or references, and no delete in the destructor. If you need shared ownership in C++, use std::shared_ptr for the parts.
  • Someone else must own the parts. Here the registered list owns the speakers. In a real system that is usually a repository or service (SpeakerRepository, Catalog, FleetService).

A common progression in interviews:

  • Bad: Event creates its own Speaker objects inside its constructor. Now the speakers cannot be reused, and the "aggregation" has quietly become composition.
  • Good: speakers are created elsewhere and added to the event.
  • Better: they are injected through the constructor or a method, and the event exposes only a read-only view of them.

7. Aggregation or Composition? A Quick Decision Guide

Common examples in LLD problems:

WholePartRelationshipWhy
LibraryBookAggregationBooks can be moved to another branch
PlaylistSongAggregationA song is in many playlists and outlives them
DepartmentEmployeeAggregationEmployees move between departments
ParkingLotParkingFloorCompositionFloors do not exist without the lot
HouseRoomCompositionRooms are destroyed with the house
ChatGroupMessageCompositionMessages belong to exactly one group

Some cases depend on the business rules. If a Cart is cleared, its CartItems are gone (composition), but the Products they point to remain (association or aggregation). When in doubt, ask the interviewer what should happen to the part when the whole is deleted.

8. Common Mistakes

  • Deleting the parts in the whole's destructor (C++) or a close() method. That breaks every other whole that shares them.
  • Creating the parts inside the whole while calling it aggregation. If the whole creates them, it is effectively composition.
  • Returning the internal list so outside code can change the whole's parts directly.
  • Copying parts into the whole instead of referring to them. The copies drift apart from the real objects.
  • Drawing a diamond on the wrong side in UML. The diamond always sits next to the whole.
  • Overthinking it. Many interviewers treat aggregation and plain association as close cousins. What matters is that you state the lifecycle clearly: who creates the part, and what happens to it when the whole goes away.

9. Summary

ConceptKey point
AggregationA whole groups parts it does not own
LifecycleParts are created outside and survive the whole
SharingA part can belong to several wholes at once
UMLHollow diamond on the whole's side
vs CompositionComposition creates its parts and destroys them with the whole (filled diamond)
Good practiceInject parts, expose a read-only view, never delete parts in the whole

Aggregation lets you model real-world groupings, such as depots and buses, groups and members, events and speakers, without tying the life of the parts to the container. That keeps your classes reusable, loosely coupled and close to how the real world works.