When modeling object-oriented systems with the Unified Modeling Language (UML), one of the most common structural patterns you will encounter is the "whole-part" hierarchy — the idea that complex objects are built from simpler constituent objects. UML 2.0 provides two specialized forms of association to capture this pattern: aggregation and composition.
At first glance, the two concepts appear nearly identical. Both describe a relationship where one class "contains" or "is made up of" other classes. However, the distinction between them carries significant implications for object ownership, lifecycle management, and part sharing — decisions that directly affect how your software is designed, implemented, and maintained.
This guide provides a comprehensive breakdown of aggregation and composition, covering their formal definitions, UML notation, behavioral differences, metamodel classification, and practical PlantUML diagram examples you can use immediately in your own projects.

Aggregation represents a loose or weak whole-part relationship. It communicates that one class acts as a collection, container, or "aggregate" of other classes, but the parts maintain their independent identity and equal-ranking status relative to the whole.
Key idea: The whole uses or references its parts, but does not own them in a strict existential sense.
Real-world analogy: A university Department and its Professor members. A professor belongs to a department, but if the department is dissolved, the professor still exists and can be reassigned elsewhere.
Composition represents a strict or strong form of aggregation. The whole exercises exclusive ownership over its parts, and the parts are existentially dependent on the whole. The relationship implies that the parts have no meaningful existence outside the context of their composite.
Key idea: The whole owns its parts. The parts are created for, and destroyed with, the whole.
Real-world analogy: A House and its Room objects. A room cannot exist independently of the house it belongs to. If the house is demolished, the rooms cease to exist as well.
The visual distinction between the two is straightforward and centers on the rhombus (diamond) symbol placed at the "whole" end of the association line.
| Relationship | Symbol | Description |
|---|---|---|
| Aggregation | ◇ (empty/white diamond) | Hollow diamond at the aggregate side |
| Composition | ◆ (filled/black diamond) | Solid diamond at the composite side |
Both symbols are placed on the end of the association line nearest to the class that represents the whole. The opposite end connects to the class that represents the part.
| Aspect | Aggregation | Composition |
|---|---|---|
| Can a part belong to multiple wholes? | ✅ Yes | ❌ No |
| Ownership | Shared / non-exclusive | Exclusive |
In an aggregation, a single part instance may be referenced by several wholes simultaneously. For example, a single Engine object could logically appear in both a Car aggregate and a Boat aggregate.
In a composition, a part instance belongs to exactly one whole at any given time. Sharing is explicitly forbidden by the semantics of the relationship.
| Aspect | Aggregation | Composition |
|---|---|---|
| Part lifecycle independent? | ✅ Yes | ❌ No |
| Part destroyed when whole is destroyed? | Typically no | Typically yes |
| Part created before whole? | Possible | Possible, but uncommon |
Aggregation: The part has an independent lifecycle. It can be created before the whole, survive the destruction of the whole, and be reassigned to a different whole.
Composition: The part is existentially dependent on the whole. While UML allows parts to be created after the whole (e.g., adding a Room to a House after construction), the parts are co-destroyed when the whole is destroyed.
| Criterion | Aggregation (◇) | Composition (◆) |
|---|---|---|
| Strength | Weak / loose | Strong / strict |
| Ownership | Non-exclusive | Exclusive |
| Part sharing | Allowed | Forbidden |
| Lifecycle dependency | Independent | Dependent |
| Co-destruction | No | Yes |
UML AggregationKind |
shared |
composite |
A common misconception is that aggregation and composition are entirely separate relationship types in UML. In reality, the UML 2.0 metamodel treats them as properties of the Property class rather than as distinct relationship classifiers.
The specific type of whole-part semantics is governed by the AggregationKind enumeration, which defines three literals:
| Literal | Meaning |
|---|---|
none |
A plain association with no whole-part semantics (the default) |
shared |
Aggregation — loose whole-part |
composite |
Composition — strict whole-part |
This means that, at the metamodel level, aggregation and composition are variations of association controlled by a tagged property, not fundamentally different structural constructs.

@startuml aggregation-example
skinparam classAttributeIconSize 0
skinparam linetype ortho
title Aggregation: Department ◇── Professor
class Department {
- name : String
- budget : Double
+ addProfessor(p : Professor)
+ removeProfessor(p : Professor)
}
class Professor {
- name : String
- employeeId : String
+ teach(course : Course)
}
' Aggregation: hollow diamond on the "whole" side
Department "1" o-- "0..*" Professor : employs >
note right of Professor
A Professor can exist
independently of any
Department and can even
belong to multiple
Departments.
end note
@enduml
Reading the diagram: The hollow diamond (o--) sits on the Department side, indicating that Department is the aggregate. A professor may belong to zero or more departments and retains an independent lifecycle.

@startuml composition-example
skinparam classAttributeIconSize 0
skinparam linetype ortho
title Composition: House ◆── Room
class House {
- address : String
- floors : Integer
+ addRoom(r : Room)
+ demolish()
}
class Room {
- name : String
- area : Double
+ calculateVolume() : Double
}
' Composition: filled diamond on the "whole" side
House "1" *-- "1..*" Room : contains >
note right of Room
A Room cannot exist
without its House.
When the House is
demolished, all its
Rooms are destroyed.
end note
@enduml
Reading the diagram: The filled diamond (*--) sits on the House side, indicating strict ownership. Every Room belongs to exactly one House, and the rooms' lifecycles are bound to the house.

@startuml side-by-side-comparison
skinparam classAttributeIconSize 0
skinparam linetype ortho
title Aggregation vs. Composition — Side by Side
package "Aggregation (Loose)" {
class University {
- name : String
}
class Student {
- studentId : String
}
University "1" o-- "0..*" Student : enrolls >
}
package "Composition (Strict)" {
class Order {
- orderId : String
- date : Date
}
class OrderLine {
- quantity : Integer
- price : Double
}
Order "1" *-- "1..*" OrderLine : consists of >
}
note bottom of Student
Students exist before
and after enrollment.
A student may attend
multiple universities.
end note
note bottom of OrderLine
An OrderLine has no
meaning without its
parent Order. Deleting
the Order deletes all
its OrderLines.
end note
@enduml

@startuml ecommerce-mixed
skinparam classAttributeIconSize 0
skinparam linetype ortho
title Mixed Aggregation & Composition in an E-Commerce Model
class Warehouse {
- location : String
- capacity : Integer
}
class Product {
- sku : String
- name : String
- price : Double
}
class ShoppingCart {
- cartId : String
- createdAt : DateTime
}
class CartItem {
- quantity : Integer
- subtotal : Double
}
class DeliveryAddress {
- street : String
- city : String
- zipCode : String
}
' --- Aggregation relationships (hollow diamond) ---
Warehouse "1" o-- "0..*" Product : stocks >
ShoppingCart "0..*" o-- "0..*" DeliveryAddress : ships to >
' --- Composition relationships (filled diamond) ---
ShoppingCart "1" *-- "0..*" CartItem : holds >
CartItem "1" *-- "1" Product : references >
note bottom of Product
Products exist independently
of any Warehouse or Cart.
(Aggregation)
end note
note bottom of CartItem
CartItems are created and
destroyed with their
ShoppingCart. (Composition)
end note
@enduml
Key takeaways from this diagram:
Warehouse aggregates Product — products exist independently and can be stocked in multiple warehouses.
ShoppingCart composes CartItem — line items have no meaning outside their cart.
ShoppingCart aggregates DeliveryAddress — an address can be shared across multiple carts or orders.
| Use Aggregation when… | Use Composition when… |
|---|---|
| Parts can exist without the whole | Parts are meaningless without the whole |
| Parts may be shared among multiple wholes | Each part belongs to exactly one whole |
| The relationship is more "referential" | The relationship is more "ownership-based" |
| You want loose coupling | You want tight encapsulation |
Example: Library → Book |
Example: Car → Engine |
💡 Tip: When in doubt, ask yourself: "If I delete the whole, should the parts be deleted too?" If the answer is yes, use composition. If no, use aggregation.
Aggregation and composition are two essential tools in the UML modeler's toolkit for expressing whole-part hierarchies with varying degrees of coupling and ownership. While they share the same underlying metamodel mechanism — the AggregationKind enumeration on the Property class — their semantic implications are profoundly different:
Aggregation (shared, ◇) models loose, flexible relationships where parts are independent, shareable, and long-lived.
Composition (composite, ◆) models strict, ownership-driven relationships where parts are exclusive, non-shareable, and existentially bound to their whole.
Choosing correctly between the two is not merely a notational exercise; it communicates critical design decisions about lifecycle management, memory ownership, and object identity to everyone who reads your diagrams — from fellow developers to system architects and stakeholders. By applying the guidelines and examples in this guide, you can model your systems with greater precision and clarity, ensuring that your UML diagrams faithfully represent the intended runtime behavior of your software.