Skip to main content

What It Is

The Composite pattern treats single things and groups of things through the same interface. A file has a size; a folder full of files (and folders) has a size too — so both implement size(), and code that sums sizes never asks which one it holds.

Composites naturally form trees: groups contain leaves and other groups, to any depth.


Example: Files and Folders

The Item interface has one method. A FileItem answers with its own size; a Folder asks everything inside and adds it up — recursion falls out for free.

One interface for leaf and group

root.size() walks the whole tree without one type check: the folder does not care whether an item is a 4 KB file or another folder hiding ten more. The docs folder answers 10, and root answers 12 — its own 2 KB file plus everything in docs.

Prompt
Write a TypeScript program showing the Composite pattern: an Item interface with a size method, a FileItem leaf holding a fixed size in KB, and a Folder class that holds Items and sums their sizes recursively. Build a root folder containing a 2 KB file and a docs folder with a 4 KB and a 6 KB file, then print the size of docs and of root.
Output: TypeScript file and captured output
One interface for leaf and group

When to Use It

Use it for tree-shaped data where groups and single items answer the same questions — file systems, menus with submenus, UI layouts, organization charts.

Skip it for flat lists. An array with a loop needs no pattern.


Pros and Cons

Pros: client code stays flat and simple; trees of any depth come for free; new leaf or group classes plug into the same interface.

Cons: the shared interface can force awkward methods on leaves (what is a file's "add child"?); very general composites become hard to constrain.