Visual Paradigm Desktop VP Online

Aggregation vs. Composition in UML 2.0: A Complete Guide to Whole-Part Relationships

Introduction

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 ownershiplifecycle 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.


1. Core Definitions

1.1 Aggregation (Shared Association)

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.

1.2 Composition (Composite Association)

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.


2. UML Notation

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.


3. Key Behavioral Differences

3.1 Part Sharing

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.

3.2 Lifecycle and Existential Dependency

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.

3.3 Summary Comparison Table

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

4. Metamodel Classification

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.


5. PlantUML Diagram Examples

5.1 Aggregation Example: Department and Professors

@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.


5.2 Composition Example: House and Rooms

@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.


5.3 Side-by-Side Comparison

@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

5.4 Complex Real-World Scenario: E-Commerce System

@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.


6. Practical Guidelines: When to Use Which

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.


Conclusion

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 managementmemory 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.

Turn every software project into a successful one.

We use cookies to offer you a better experience. By visiting our website, you agree to the use of cookies as described in our Cookie Policy.

OK