Skip to content

Design Pattern: Composite (Structural)

Treat a tree and a single item the same way

Builds on Interfaces and Class Relationships: Association, Aggregation and Composition

Stage 3core2 min read

1. Introduction

A shopping cart can hold a single book. It can also hold a gift box with other items, even other boxes, inside. You want the price without checking which one you have.

The Composite Pattern is a structural design pattern (about how classes fit together). It arranges objects in a tree where a part is one item or a group of items (a part-whole hierarchy). Code treats one item and a whole group the same way.


2. Problem It Solves

In an e-commerce checkout, products sit inside bundles. Without this pattern, the client code (the code that uses these classes) must check by hand whether each thing is a single item or a group:

  • Class Explosion: Product and ProductBundle are separate types, and they share no interface (a common list of methods).
  • Polymorphism Breakage: Polymorphism means one call works on many types. Here it breaks, so you must use instanceof (a check of an object's type) again and again before you act.
  • Rigid Structure: A ProductBundle cannot hold another ProductBundle, so nesting is impossible (for example, a combo pack inside a larger gift box).

3. Class Diagram

The diagram shows the Leaf (Product) and the Composite (ProductBundle). Both implement the CartItem interface.

Loading diagram…

4. Leaf vs. Composite

Leaf (The Atomic Object)

  • Definition: A simple object that holds no other objects inside it.
  • Role: Product is the Leaf. It stands for one item (a book or a phone) and knows its own price.

Composite (The Container)

  • Definition: An object that holds many CartItem objects. These can be Leaves or other Composites.
  • Role: ProductBundle is the Composite. It delegates (passes the work on) getPrice() and display() to each child, then adds up the prices.

5. Advantages and Disadvantages

AdvantagesDisadvantages
Uniformity: One item and a group are used in the same way.Over-Generalization: Treating everything alike can hide real differences between types.
Open/Closed Principle: You can add new item types without editing existing code.Complexity: Too much for a flat list.
Recursive Depth: Groups can sit inside groups, as deep as you need (combos inside kits inside boxes).SRP Violation: In general (not in this example), in a large system one class may handle both business logic and the tree structure (SRP: one job per class).

6. Real-World Use Cases

  1. File Systems: Folders (Composites) containing Files (Leaves) and other Sub-folders.
  2. UI Toolkits: A Panel (Composite) containing Buttons (Leaves) and other Panels.
  3. E-commerce: Product Bundles and Kits, as in the refactored code.

Key Takeaway: The "Part-Whole" Hierarchy

Use the Composite Pattern when your data forms a Tree Structure. Make the "Whole" (Bundle) implement the same interface as the "Part" (Product). Then you no longer need type checks, and the structure can grow easily.

In this topic

Done with this topic?

How well do you know it?

PreviousDesign Pattern: Facade (Structural)