If you've ever drawn a UML class diagram and hesitated between using a filled diamond or an empty diamond, you're not alone. Composition and aggregation look almost identical in notation, but they describe fundamentally different relationships between classes. Getting them wrong doesn't just make your diagram inaccurate it can lead to flawed software design, broken assumptions in your code, and confusion for any developer who reads your diagram later.
What's the difference between composition and aggregation in a UML class diagram?
Both composition and aggregation are forms of association in UML. They both describe a "has-a" relationship where one class contains or owns instances of another class. The difference comes down to lifecycle dependency.
Aggregation means a class contains another class, but the contained object can exist independently. If the parent is destroyed, the child survives. Think of it as a "has-a" relationship with loose coupling.
Composition means a class contains another class, and the contained object cannot exist without the parent. If the parent is destroyed, the child is destroyed too. This is a stronger "owns-a" relationship with tight coupling.
In UML notation:
- Aggregation uses an empty (white) diamond on the side of the whole class
- Composition uses a filled (black) diamond on the side of the whole class
Why does the distinction between composition and aggregation actually matter?
On paper, it might seem like a small detail. But in practice, it communicates critical design intent to other developers. When someone reads your diagram, the type of relationship tells them:
- Whether deleting an object will cascade and delete its parts
- Whether parts can be shared between multiple parent objects
- How to handle object creation and destruction in code
For example, if you're designing a system and you mark the relationship between Order and OrderItem as aggregation instead of composition, a developer might assume order items can exist without their parent order which could lead to orphaned data in your database.
This matters even more when you move from diagrams to actual code, as explained in our guide on generating code from UML class diagrams for Java developers.
What does composition look like with a real example?
Consider a House and its Room objects:
- A
Houseis composed of multipleRoomobjects - If the house is demolished, the rooms cease to exist
- A room doesn't make sense on its own it's tightly bound to the house
In UML, you'd draw a filled diamond from House to Room. In code, this typically means the House class creates and owns the Room objects, and is responsible for cleaning them up.
Another classic example: TextEditor and Document. If you close the editor without saving, the in-memory document is gone. The document's lifecycle is controlled by the editor.
What does aggregation look like with a real example?
Think about a University and its Student objects:
- A university has students (aggregation)
- If the university shuts down, the students still exist they can transfer to another school
- The students are not destroyed when the parent entity goes away
In UML, you'd draw an empty diamond from University to Student. The relationship is "has-a" but without ownership over the lifecycle.
A Playlist and Song is another good example. Deleting a playlist doesn't delete the songs from your music library. The songs exist independently and can belong to multiple playlists.
Can an object be part of both composition and aggregation relationships?
Yes. A single class can participate in different types of relationships with different classes. For example, a Wheel might be in a composition relationship with Car (wheels are created for and die with the car in this model), while the Car itself might be in an aggregation relationship with a Dealership (cars can be moved between dealerships).
The relationship type isn't about the object itself it's about how two specific classes interact. This is a point that gets confused often, especially in inheritance examples in UML class diagrams, where beginners mix up "is-a" and "has-a" relationships.
What are the most common mistakes people make?
Here are the errors I see most often when reviewing UML diagrams:
- Using aggregation when composition is correct. If the child object has no reason to exist without the parent, it's composition not aggregation. Be honest about the lifecycle.
- Overusing composition. Not every "has-a" relationship is composition. If parts can be reassigned, shared, or outlive the parent, it's aggregation.
- Confusing aggregation with simple association. Aggregation implies a whole-part relationship. If there's no meaningful whole-part structure, a plain association line (no diamond) is more accurate.
- Ignoring multiplicity. Always indicate how many instances are involved. A
Carhas exactly 4Wheelobjects, not an unspecified number. - Mixing up diamonds. Empty = aggregation, filled = composition. It's a small visual difference that carries a big semantic difference.
How do you decide which one to use in your diagram?
Ask yourself these two questions:
- Can the part exist without the whole? If no → composition. If yes → aggregation.
- Can the part be shared between multiple instances of the whole? If yes → aggregation (or plain association). If no → composition.
When in doubt, lean toward the simpler relationship. Labeling everything as composition when it isn't creates false constraints in your design. You can always refine later, but starting with accurate relationships saves time.
You can see working examples of both relationships with actual code mappings in our UML composition vs aggregation code examples.
Quick reference: composition vs aggregation side by side
| Aspect | Aggregation | Composition |
|---|---|---|
| Diamond symbol | Empty (white) | Filled (black) |
| Lifecycle dependency | Part can outlive the whole | Part dies with the whole |
| Sharing | Parts can be shared | Parts belong to one parent only |
| Relationship strength | Weaker | Stronger |
| Example | Team and Player | Body and Heart |
Before you finalize your next UML diagram, use this checklist:
- ☐ Identify every "has-a" relationship in your diagram
- ☐ For each one, ask: can the child exist independently?
- ☐ Ask: can the child be shared across multiple parents?
- ☐ Use a filled diamond only when the parent fully owns and controls the child's lifecycle
- ☐ Use an empty diamond when the relationship is whole-part but the part is independent
- ☐ Add multiplicity to both ends of the relationship
- ☐ Review with a teammate if they misunderstand the relationship, your notation might be wrong
Uml Class Diagram Inheritance Examples for Beginners: a Simple Guide
Uml Class Diagram for Complex Real-World Application
Uml Class Diagram Code Generation for Java Developers
Uml Sequence Diagram Symbols and Meanings – Complete Syntax Guide
Flowchart Symbols and Their Meanings Explained
Sequence Diagram Syntax Reference Guide