Structural · DWG NO. 012

Composite

Treat a single item and a group of items through the same interface, so client code doesn't need to know which it has.

TypeStructural
ScopeTree structure
ComplexityMedium
Common inFile systems, UI trees, org charts, menus

"Is this one item or a folder of items?" shouldn't be the caller's problem

Calculating a folder's total size means handling files and folders differently everywhere you touch them — a file has a size property, a folder has to sum its children, and folders can contain folders. Every caller ends up re-implementing that branch.

Leaves and branches share one interface

Both `File` (leaf) and `Folder` (composite) implement the same method, e.g. `getSize()`. A folder's implementation just calls `getSize()` on each child and sums the results — including child folders, recursively. Callers never check which kind of node they have.

FolderFileFolderFileFile

Files and folders behind one interface

`getSize()` works identically whether it's called on a single file or on the folder at the very top of the tree.

filesystem-composite.js
class File {
  constructor(name, size) { this.name = name; this.size = size; }
  getSize() { return this.size; }
}

class Folder {
  constructor(name) { this.name = name; this.children = []; }
  add(node) { this.children.push(node); return this; }
  getSize() {
    return this.children.reduce((sum, child) => sum + child.getSize(), 0);
  }
}

const src = new Folder("src")
  .add(new File("index.js", 2_000))
  .add(new File("utils.js", 800));

const project = new Folder("project")
  .add(src)
  .add(new File("README.md", 400));

console.log(project.getSize()); // 3200 — files + nested folder, uniformly

Trade-offs