Concepts•Jun 2026•4 min read

Composite Pattern vs Visitor Pattern

Two GoF patterns people confuse because they both crawl tree structures. They solve opposite problems. Composite builds the tree; Visitor adds operations to it without touching the classes. Pick by what changes most: the shapes or the operations.

The short answer

Composite Pattern over Visitor Pattern for most cases. Composite is a foundational structural pattern you reach for constantly — any part-whole hierarchy (DOM, file systems, UI trees, ASTs) wants it, and it earns.

  • Pick Composite Pattern if have a part-whole hierarchy and want clients to treat leaves and containers uniformly — trees, UI components, file systems, nested menus
  • Pick Visitor Pattern if your class hierarchy is STABLE but you keep adding new operations over it (type-check, then optimize, then codegen over the same AST), and you'll accept double-dispatch boilerplate
  • Also consider: They compose: build the tree with Composite, then run Visitors across it. That pairing is the legitimate use of Visitor — and the only time most people should touch it.

— Nice Pick, opinionated tool recommendations

They aren't even competing

Half the people Googling this matchup are confused, so let's kill the framing. Composite is structural: it composes objects into trees and lets you treat a single leaf and a whole subtree through one interface. Visitor is behavioral: it bolts a new operation onto an existing object structure without editing those objects' classes. One answers 'how do I model a nested thing,' the other answers 'how do I add the fifteenth operation over that nested thing without touching fifteen classes.' They show up together because Visitor's textbook example IS walking a Composite tree. So the real question isn't 'which pattern' — it's 'which problem do I have.' If you don't have a stable class hierarchy that you're piling operations onto, you don't have a Visitor problem, and reaching for it is cargo-culting. Most codebases have a Composite problem and invent a Visitor problem to feel clever.

Composite: cheap, everywhere, hard to overuse

Composite is one of the highest-leverage patterns in the GoF book because part-whole hierarchies are everywhere: the DOM, React/SwiftUI component trees, filesystem nodes, org charts, nested form fields, scene graphs. The win is uniformity — client code calls render() or size() on a node without branching on 'leaf or container,' and the container just forwards to children. That collapses a pile of conditional tree-walking into clean recursion. The real tradeoff is the leaky interface: do you put add(child) on the common Component interface (transparent — leaves throw on it) or only on Composite (safe — but clients must downcast)? Transparency is the usual pick; you eat a runtime error on a meaningless leaf.add() in exchange for not type-juggling everywhere. That's a fair trade. Composite's failure mode is mild — an awkward interface — not the structural lock-in Visitor inflicts.

Visitor: powerful, and a tax you pay forever

Visitor's pitch is real: separate algorithms from the objects they run on, so adding a new operation is one new class instead of edits to twenty element types. Compilers love it — one AST, many passes (typecheck, optimize, emit). But read the fine print. Visitor solves the expression problem in exactly one direction: operations get cheap, NEW TYPES get brutal. Add one element class and you must touch every visitor interface and every concrete visitor — the opposite of open/closed. It demands double dispatch (accept(visitor) calling visitor.visit(this)), which is ceremony in every language and genuinely ugly in ones without method overloading. It also pressures you to widen element accessors to public so visitors can read state, eroding encapsulation. Choose Visitor only when you are certain the type set is frozen and operations will keep multiplying. Guess wrong and you've welded the worst case into your architecture.

The decision rule

Ask one question: what's volatile — the SHAPES or the OPERATIONS? If you're adding new node types over time (new UI widgets, new file kinds), use Composite and put behavior as methods on the nodes; adding a type is one self-contained class. If the type set is locked and you keep adding cross-cutting operations over it, Visitor earns its boilerplate. In modern languages, weigh the alternatives honestly: sealed types plus pattern matching (Scala, Rust enums, Java switch patterns) give you Visitor's 'add an operation cheaply' benefit with none of the double-dispatch sludge — Visitor is partly a workaround for languages that lacked exhaustive matching. Composite has no such substitute; recursion over a uniform interface is just the right model for trees. So Composite is the default you'll use for a career, and Visitor is the specialist you call in when a compiler-shaped problem actually shows up. Don't summon the specialist for a sapling.

Quick Comparison

FactorComposite PatternVisitor Pattern
Problem solvedModel part-whole hierarchies; treat leaf and tree uniformlyAdd new operations over a fixed class hierarchy without editing it
Breadth of useUbiquitous: DOM, UI trees, filesystems, scene graphsNiche: compilers, ASTs, stable structures with many passes
Cost / boilerplateLow — one interface, forwarding recursionHigh — double dispatch, visit-per-type ceremony
Adding a new type laterEasy — one new node class, behavior local to itBrutal — touch every visitor interface and implementation
Adding a new operation laterEdit every node class (or pair with Visitor)Cheap — one new visitor class

The Verdict

Use Composite Pattern if: You have a part-whole hierarchy and want clients to treat leaves and containers uniformly — trees, UI components, file systems, nested menus.

Use Visitor Pattern if: Your class hierarchy is STABLE but you keep adding new operations over it (type-check, then optimize, then codegen over the same AST), and you'll accept double-dispatch boilerplate.

Consider: They compose: build the tree with Composite, then run Visitors across it. That pairing is the legitimate use of Visitor — and the only time most people should touch it.

Composite Pattern vs Visitor Pattern: FAQ

Is Composite Pattern or Visitor Pattern better?

Composite Pattern is the Nice Pick. Composite is a foundational structural pattern you reach for constantly — any part-whole hierarchy (DOM, file systems, UI trees, ASTs) wants it, and it earns its keep with almost no ceremony. Visitor is a niche, high-cost tool that's correct maybe one time in twenty and miserable the other nineteen. Composite wins because it's broadly useful and cheap; Visitor is narrowly useful and expensive.

When should you use Composite Pattern?

You have a part-whole hierarchy and want clients to treat leaves and containers uniformly — trees, UI components, file systems, nested menus.

When should you use Visitor Pattern?

Your class hierarchy is STABLE but you keep adding new operations over it (type-check, then optimize, then codegen over the same AST), and you'll accept double-dispatch boilerplate.

What's the main difference between Composite Pattern and Visitor Pattern?

Two GoF patterns people confuse because they both crawl tree structures. They solve opposite problems. Composite builds the tree; Visitor adds operations to it without touching the classes. Pick by what changes most: the shapes or the operations.

How do Composite Pattern and Visitor Pattern compare on problem solved?

Composite Pattern: Model part-whole hierarchies; treat leaf and tree uniformly. Visitor Pattern: Add new operations over a fixed class hierarchy without editing it.

Are there alternatives to consider beyond Composite Pattern and Visitor Pattern?

They compose: build the tree with Composite, then run Visitors across it. That pairing is the legitimate use of Visitor — and the only time most people should touch it.

🧊
The Bottom Line
Composite Pattern wins

Composite is a foundational structural pattern you reach for constantly — any part-whole hierarchy (DOM, file systems, UI trees, ASTs) wants it, and it earns its keep with almost no ceremony. Visitor is a niche, high-cost tool that's correct maybe one time in twenty and miserable the other nineteen. Composite wins because it's broadly useful and cheap; Visitor is narrowly useful and expensive.

Related Comparisons

Disagree? nice@nicepick.dev