Patterns: composition · 3 MIN READ

Composite: treat leaves and groups uniformly

Define recursive behavior while guarding the shape of the structure.

Define recursive behavior while guarding the shape of the structure. Composite exposes one operation on both individual values and groups. Trace the worked Go example, then compare the benefit with the cost before applying this design to your own project.

Structural pattern · A MAP OF THE IDEA

  1. Client calls one operation
  2. Group delegates to children
  3. Leaves compute the base result

Useful when

  • A tree has meaningful uniform operations
  • Clients should not branch on leaf versus group

Watch out

  • Cycles and depth need a policy
  • Uniform interfaces can expose meaningless leaf operations

Implementation & operation cost: Medium

Fit depends on the task

Small tool or CLI4/5
Domain-rich application4/5
Independent distributed services3/5

Editorial suitability, not benchmarks or a universal ranking. Styles describe different axes and can be combined.

01

The design decision

Composite exposes one operation on both individual values and groups. A file tree can compute size by summing children, while a leaf reports its own size. Decide whether the structure is a true tree; cycles require detection or a different traversal contract.

02

A complete Go example

Read this program from the entry point and follow the calls shown in the diagram. The output is included at the end so you can check the behavior without a compiler.

go
package main

import (
	"fmt"
)

type Sized interface{ Size() int }
type File int

func (f File) Size() int { return int(f) }

type Folder []Sized

func (f Folder) Size() int {
	n := 0
	for _, child := range f {
		n += child.Size()
	}
	return n
}

func main() {
	root := Folder{File(4), Folder{File(2), File(3)}}
	fmt.Println(root.Size())
}

// Output:
// 9
Read the code

File and Folder satisfy the same Size operation, so the root recursively sums to nine. The interface hides whether a child is a leaf or group. This example assumes an acyclic owned tree and small nonnegative sizes.

03

Tradeoffs and the simpler alternative

Uniform operations can be elegant, but a group-only mutation API need not be forced onto leaves. Define depth limits or iterative traversal for untrusted trees. Shared nodes and cycles change ownership and may cause duplicate counting or infinite recursion.

TAKE THIS WITH YOU

Gives leaves and groups a common recursive operation. Uniform operations can be elegant, but a group-only mutation API need not be forced onto leaves. Define depth limits or iterative traversal for untrusted trees. Shared nodes and cycles change ownership and may cause duplicate counting or infinite recursion.

Check your understanding

Which statement best describes Composite: treat leaves and groups uniformly?

Go to the source

Progress stays in this browser. No account needed.