Composition
Composition is aggregation with the leash removed: a whole made of parts, except this
time the parts have no life of their own. A University consists of Departments, and
if the university shuts down, so does every department in it - there is no "department
without a university" in this model, full stop.
Definition: "has-a", with exclusive ownership
Where aggregation's parts are handed to the whole from outside, composition's parts are typically created by the whole, for the whole, and destroyed with it. The part's entire existence is scoped to its owner:
Notice the difference from aggregation's addProfessor(Professor p): that method
received an already-existing object. This one calls new Department(...) itself.
Nothing outside University ever gets a chance to hand it a pre-built Department,
because a Department divorced from some university doesn't mean anything in this
design.
UML notation
Composition draws as a solid line with a filled (solid black) diamond at the whole's end - same shape and position as aggregation's diamond, just filled in instead of hollow. That single filled-vs-hollow distinction is the one piece of UML notation people misread most often, precisely because the two diagrams otherwise look identical.
Multiplicity
A University typically has one or more Departments (1 - 1..*, since a university
with zero departments is an edge case worth allowing but rarely modeled as required),
and - unlike aggregation - each Department belongs to exactly one university,
never zero and never more than one. That "exactly one, permanently" is multiplicity
quietly encoding the same exclusivity the filled diamond already states graphically.
Directionality
Composition is almost always modeled with the whole holding the parts, and it's common
- more common than in aggregation - for the part to hold a back-reference to its owner,
since the part is conceptually inseparable from it anyway (see the
thispassed intonew Department(deptName, this)above). That back-reference doesn't carry the same synchronization risk called out on the association page: becauseUniversityalone controls when departments are created or removed, there's only ever one place that has to keep the pointer correct.
Worked example
The same shape shows up anywhere a whole is meaningless in pieces: an Order composed
of LineItems (a line item referencing no order is just an orphaned quantity-and-price,
not a business object), a TreeNode composed of its child TreeNodes, a Document
composed of its Paragraphs. In every case, the constructor of the whole is the one and
only place a part gets created.
Telling composition apart from its neighbours
The question that matters is the one from the aggregation page,
just asked from the opposite direction: can the part be handed in from outside, or
created independently and reused elsewhere? If yes, you're describing aggregation, not
composition, no matter how tightly related the two classes feel. Department fails that
test - nothing outside University calls new Department(...), and there is no
addDepartment(Department d) overload waiting to accept a pre-built one. Professor, on
the aggregation page, passes it easily - departments receive already-existing professors
without ever constructing one.
Common mistakes
- Exposing a constructor or setter that accepts a fully-built part from outside.
The instant
addDepartment(Department d)exists as a public method, an external caller can hand in aDepartmentbuilt (and potentially shared) elsewhere, and the relationship has quietly become aggregation - the diamond on the diagram is now lying. - Confusing "declared as a nested class" with composition. Composition is about lifecycle ownership, not syntax. A part stored in an external collection and passed around freely is not composed just because it happens to be a private field; a part referenced only via a builder pattern that hands the finished whole+parts back as one unit can still be genuine composition even though no code looks visually "nested."
- Forgetting that composition can still have multiplicity greater than one on the
part side. Composition is not "always one part" - a
Universitycan compose manyDepartments at once. The exclusivity is about ownership per part, not about how many parts there are.
Try it yourself: model a Car and its Engine. In your design, can an engine be
removed from one car and installed in another? If the answer is yes, you've actually
modeled aggregation - what would need to change about the code for it to become genuine
composition instead?
Check yourself
Two UML diagrams both show a diamond between University and Department, but one is filled and one is hollow. What is the practical difference?