What if a relationship is so strong that the "part" is meaningless and cannot even exist without the "whole"?
This is the world of Composition.
Composition is the strongest form of association in object-oriented design. It models a “has-a” relationship between a whole and its parts—but unlike aggregation, composition comes with ownership and lifecycle dependency.
When you use composition, you're saying:
Composition is a special type of association that signifies strong ownership between objects. The “whole” class is fully responsible for creating, managing, and destroying the “part” objects. In fact, the parts cannot exist without the whole.
If the part makes no sense without the whole, use composition.
Imagine a House and its Rooms:
This is a textbook example of composition. The rooms are tightly bound to the house—not just logically, but in lifecycle and ownership as well.
In UML class diagrams, composition is represented by a filled diamond (◆) at the “whole” end of the relationship.
This diagram means:
House owns one or more Room objects.Rooms do not exist independently of the House.House is deleted, all its Rooms are also deleted automatically.In other words, the child class (Room) is tightly bound to the lifecycle of the parent class (House).
Let’s model above example using code.
Room classHouse classHouse creates, manages, and owns its Room objects.Room objects do not exist independently outside the context of the House.Room instances.House is deleted (e.g., garbage collected), the Rooms are destroyed too.This demonstrates a true composition relationship—where object ownership and lifecycle are tightly coupled.
Use composition when:
Composition is a preferred alternative to inheritance when building flexible systems.
“Favor composition over inheritance.” — GoF Design Principle
For example:
Vehicle can compose an Engine interface.PetrolEngine, ElectricEngine, or HybridEngine at runtime.This leads to cleaner, testable, and decoupled code.
Let’s compare association, aggregation, and composition side-by-side to understand how they differ in ownership, lifecycle, reusability, and usage in real systems.
Feature | Association | Aggregation | Composition |
|---|---|---|---|
Ownership | ❌ None | ❌ Weak — has-a | ✅ Strong — owns-a |
Lifecycle | ❌ Independent | ❌ Independent | ✅ Dependent — part dies with whole |
Tightness | Loose coupling | Moderate coupling | Tight coupling |
Multiplicity | Flexible (1:1, 1:N, N:N) | Whole can group many parts | Whole composed of integral parts |
Reusability | High — parts reusable | Moderate — parts often reused | Low — parts not reused outside |
UML Symbol | Solid Line | Hollow Diamond (◊) | Filled Diamond (◆) |
Real Example |
|
|
|
So far, we’ve explored how objects in OOP can be connected in increasingly stronger ways, from simple associations, to looser aggregations, to tightly bound compositions.
But in many real-world designs, classes also rely on each other temporarily, not as part of their structure but during specific actions or method calls.
These short-lived, non-owning relationships are modeled through Dependency — the weakest form of connection in OOP.
Lets explore that in the next chapter.