Skip to main content

Aggregation

Aggregation is association with a shape to it: a whole made of parts, where the parts have their own independent existence. A Department has Professors, but a professor who leaves - or a department that shuts down - doesn't take the other one with it. That independence is the entire idea, and it's also the thing people get backwards.

Definition: "has-a", without owning the lifecycle

Aggregation is a whole/part relationship: the whole is described in terms of the parts it's made of, but the parts can be created before the whole exists, handed to it, removed from it, and reused somewhere else entirely. A Department doesn't manufacture its Professors - they're hired (created elsewhere), assigned to the department, and can move to another one without ceasing to exist:

class Department {
private String name;
private List<Professor> professors = new ArrayList<>();
 
void addProfessor(Professor p) { // receives an already-existing Professor
professors.add(p);
}
}

Notice what's absent: no new Professor(...) inside Department. The department receives professors from outside, which is exactly what makes their lifecycle independent of its own.

UML notation

Aggregation draws as a solid line with a hollow (unfilled) diamond at the whole's end - the diamond sits on Department, not on Professor, because Department is the thing described in terms of parts. An open arrowhead at the part's end is optional and just marks navigability, the same as any association.

DepartmentProfessor
A Department aggregates Professors - hollow diamond on the whole, Department. Delete the department, the professors are still around.

The single detail worth memorizing: hollow diamond, on the whole. A filled diamond in the same spot means composition instead - a different lifecycle guarantee entirely, covered on the next page.

Multiplicity

A Department typically aggregates many Professors (1 - * read at the professor end), and in most real academic models a Professor can belong to more than one department at once, which makes the full picture * - * from the professor's side even though any one Department -> Professor aggregation link is drawn simply as shown above. Multiplicity here answers "how many," never "who owns whom" - that's a separate question this page exists to answer.

Directionality

Aggregation is usually modeled unidirectionally, whole-to-part: Department holds a list of Professors, and Professor doesn't hold a list of departments back. Add that reverse reference only if something genuinely needs to ask "which departments is this professor in" - and remember from the association page that adding it means two collections to keep in sync (adding a professor to a department now means updating both Department.professors and Professor.departments).

Worked example

class Professor {
private String name;
// No reference back to any Department - this object doesn't know
// or care who currently aggregates it.
}
 
class Department {
private String name;
private final List<Professor> professors = new ArrayList<>();
 
void addProfessor(Professor p) {
professors.add(p);
}
 
void removeProfessor(Professor p) {
professors.remove(p); // the professor object itself is untouched
}
}

Closing a Department - discarding its Department object - does nothing to any Professor referenced in its list. They exist independently in whatever created them (a Faculty registry, most likely) and can be aggregated into a different department tomorrow.

Telling aggregation apart from its neighbours

  • Aggregation vs. composition - the one that matters. Ask exactly one question: does destroying the whole destroy the part? If a professor can survive their department closing, that's aggregation. If a LineItem cannot possibly exist once its Order is gone, that's composition. A second, correlated signal: aggregated parts are usually shareable across multiple wholes (one professor, several departments); composed parts usually are not (one LineItem belongs to exactly one Order, ever).
  • Aggregation vs. plain association. Here's the uncomfortable truth: in code, aggregation and a plain "has a collection of" association can look identical - both are just a field holding a reference or a list. The diamond is a design statement ("I think of these as my parts, my roster, my components") rather than something a compiler can verify. Don't lose sleep over drawing a diamond versus a plain line for a borderline case; do lose sleep over aggregation versus composition, because that distinction has real, checkable consequences for who calls new and who calls delete.

Common mistakes

  • Drawing the hollow diamond and then coding exclusive ownership anyway - having Department's constructor call new Professor(...) directly makes the code a composition no matter what the diagram claims. The notation and the code must agree.
  • Putting the diamond on the wrong end. The diamond sits on the whole (Department here), never on the part. A diamond on Professor would claim professors are made of departments, which is backwards.
  • Assuming aggregation means "read-only" or "borrowed." Aggregation says nothing about mutability or who's allowed to change the part - only about who controls its lifecycle. A department can absolutely update a professor's tenure status; it just can't be the reason the professor object stops existing.

Try it yourself: model a Playlist and the Songs inside it. Songs live in a shared catalog and can appear in many playlists at once; deleting a playlist should never delete a song. Where does the hollow diamond go, and what would have to change about the code for this to become composition instead?

Check yourself

Question 1 of 3

In an aggregation between Department and Professor, which class gets the hollow diamond, and why?