Composite means: build a tree of objects — folders containing files, bundles containing products — and let a single leaf and a whole group answer the same calls through one shared interface.
A file and a folder both answer “what is your size?” A product and a gift set both answer “what is your price?” The caller never needs a special case for “is this a group?”
Two roles show up:
Leaf — an individual thing with no children (a file, a single item).
Composite — a thing that contains children, which may themselves be leaves or composites (a directory, a bundle).
Both implement the same component interface. A composite forwards operations to its children and combines the results.
The problem it solves
Without Composite, totaling a group of things often turns into type checks:
if isinstance(thing, Bundle): pass # walk childrenelif isinstance(thing, Item): pass # use item price
if (thing instanceof Bundle) { // walk children} else if (thing instanceof Item) { // use item price}
switch t := thing.(type) {case Bundle: _ = t // walk childrencase Item: _ = t // use item price}
if (thing instanceof Bundle) { // walk children} else if (thing instanceof Item) { // use item price}
Every new operation — print a label, apply a discount, export to JSON — risks another nest of type checks. Composite moves the branching into the objects themselves: leaves answer directly, groups ask their children.
Bundles can nest inside bundles. The total still works, no matter how deep.
When it helps
Use Composite when your domain is naturally a tree and the same operations make sense on both leaves and groups: size, price, draw, validate, export.
It shines when client code would otherwise fill up with “if leaf / if group” branches for every new feature.
When it hurts
If the structure is flat — just a list of independent items — Composite adds ceremony without benefit.
Be careful with operations that only make sense for groups, like add(child). If you put add on the shared interface, leaves must either throw or no-op, which can surprise callers. Many designs keep child management on the composite type only. Also watch performance on huge trees: a naive recursive size walk touches everything every time.
Practical tips
Define a small component interface with operations meaningful for both leaves and groups.
Keep leaf classes simple; put child lists only on composites.
Prefer recursion that is easy to read over clever micro-optimizations, until profiling says otherwise.
Document whether the order of children matters.
Do not force Composite onto problems that are really just plain collections.
Check your understanding
What is Composite, in one sentence?
A design that lets individual objects and groups of objects share one interface in a tree.
What is a leaf?
A node with no children.
What is a composite?
A node that contains children and usually forwards operations to them.
Why do callers like it?
They can ignore the difference between one item and a nested group.
What to learn next
Next: Strategy Pattern — the focus shifts from how objects are arranged to how behavior is chosen and swapped.