AlgoMaster Logo

Composition

Last Updated: February 12, 2026

Ashish

Ashish Pratap Singh

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. It represents the strongest form of "has-a" relationship, where the whole owns the parts and controls their lifecycle.

When you use composition, you're saying:

  • “This object is composed of other objects.”
  • “And if the container goes away, so do its parts.”

1. What is Composition?

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.

Key Characteristics of Composition:

  • Represents a strong “has-a” relationship.
  • The whole owns the part and controls its lifecycle.
  • When the whole is destroyed, the parts are also destroyed.
  • The parts are not shared with any other object.
  • The part has no independent meaning or identity outside the whole.

If the part makes no sense without the whole, use composition.

2. UML Representation

In UML class diagrams, composition is represented by a filled diamond (◆) at the “whole” end of the relationship. This is in contrast to aggregation's hollow diamond (◊) and association's plain solid line.

The diagram shows two classes connected by composition:

  • Order owns and manages a list of LineItem objects. The 1 to * multiplicity means one order can contain many line items.
  • LineItem is a dependent entity. It holds data about a single product in the order (name, quantity, unit price), but it has no identity or purpose outside of its parent order.
  • The filled diamond (*--) on the Order side is the UML notation for composition. It signals that Order is the "whole" and LineItem is the "part," and that the line items are owned by the order.

Multiple Compositions

A class can be composed of multiple other objects. A Car is composed of an Engine, a Transmission, and a Chassis. These are integral parts of the car. You don't take the engine out and share it between two cars simultaneously. If the car is scrapped, these parts are scrapped with it.

In the software model, the Car creates these components and controls their lifecycle.

The filled diamonds on the Car side tell you: Car creates and owns these components. They don't float around the system independently.

3. Code Example

Let's model the ordering scenario. An Order composes multiple LineItem objects. The order creates line items internally when items are added, and destroys them when the order is destroyed.

Pay attention to three things that make this composition:

  • The order creates its own line items. The addItem() method takes raw data (product name, quantity, price) and internally creates a new LineItem(...). The line items are not passed in from outside. This is the key structural difference from aggregation, where parts are created externally and passed into the whole.
  • Line items have no independent existence. There is no LineItem floating around in the system outside of an Order. No other class holds a reference to these line items. They are born inside the order and die with the order.
  • Destroying the order destroys all line items. When the Order object is garbage collected (or goes out of scope in C++), all its LineItem objects are destroyed too. No orphaned line items, no cleanup code, no dangling references.

This is a true composition relationship: the parts exist only within the context of the whole, and their lifecycle is completely controlled by it.

4. When to Use Composition

Use composition when you can answer "yes" to these questions:

  • Is the part meaningless without the whole? A line item without an order has no purpose. A room without a house makes no sense. If the part loses its identity outside the whole, that's composition.
  • Should the whole control the part's lifecycle? If the whole creates the parts and destroys them, that's composition. If the parts are created externally and passed in, that leans toward aggregation.
  • Are the parts exclusive to one whole? If a part belongs to exactly one whole and is never shared, that's composition. If the same part can appear in multiple wholes (like a song in multiple playlists), that's aggregation.
  • Do you want to model strong containment? When the relationship is "is composed of" rather than "groups together," composition is the right choice.

Composition is a preferred alternative to inheritance when building flexible systems.

Favor composition over inheritance.” — GoF Design Principle

Why?

  • You can build complex behavior by composing smaller, reusable parts.
  • It avoids the tight coupling and fragility of inheritance hierarchies.
  • You can swap out parts dynamically to modify behavior.

For example:

  • A Vehicle can compose an Engine interface.
  • Swap between PetrolEngine, ElectricEngine, or HybridEngine at runtime.

This leads to cleaner, testable, and decoupled code.

5. Composition vs Aggregation vs Association

Let’s compare association, aggregation, and composition side-by-side to understand how they differ in ownership, lifecycle, reusability, and usage in real systems.

Scroll
FeatureAssociationAggregationComposition
OwnershipNoneWeak -- has-aStrong -- owns-a
LifecycleIndependentIndependentDependent -- part dies with whole
TightnessLoose couplingModerate couplingTight coupling
MultiplicityFlexible (1:1, 1:N, N:N)Whole can group many partsWhole composed of integral parts
ReusabilityHigh -- parts reusableModerate -- parts often reusedLow -- parts not reused outside
UML SymbolSolid LineHollow Diamond (◊)Filled Diamond (◆)
Who creates parts?Either side or externalExternal -- passed inWhole -- created internally
Real ExampleStudent ↔ CoursePlaylist → SongOrder → LineItem

Think of it like this:

  • Association is a general connection: two classes simply know about each other.
  • Aggregation is a grouping: the whole and parts can exist independently.
  • Composition is an ownership: the part’s existence is bound to the whole.

Decision Flowchart