Browse Java Design Patterns & Enterprise Application Architecture

Component, Leaf, and Composite Classes

Design the three Composite roles in Java deliberately so the shared contract stays useful and child-management rules stay explicit.

Composite uses three conceptual roles:

  • Component: the shared client-facing contract
  • Leaf: a node with no children
  • Composite: a node that owns children

The interesting design decision is what belongs on the Component contract.

Keep The Component Contract Focused

Put operations on the component only when all nodes can support them meaningfully. If child-management methods such as add, remove, or children do not make sense for leaves, do not force them onto the shared interface just to satisfy a textbook diagram.

In Java, a narrow component interface often works better than a “transparent” composite interface that makes leaves throw UnsupportedOperationException.

Leaves Should Stay Simple

A leaf usually owns:

  • atomic state
  • direct implementation of the shared operation
  • no child-management responsibility

If leaves start accumulating child-like behavior, the model may not actually need two roles.

Composites Need Strong Invariants

The composite class owns:

  • child collection management
  • traversal behavior
  • aggregation logic
  • invariants such as “no cycles” or “no duplicate child under the same parent”

That is where most bugs live.

Review Rule

Design the component API for client needs, not for diagram symmetry.

Loading quiz…
Revised on Thursday, April 23, 2026