Motivation: An application has recursive groupings of primitives and containers (e.g., files and directories, basic shapes and compound shapes), and client code should treat individual elements and compositions uniformly.

Intent: Compose objects into tree structures and let clients work with individual objects and compositions through a single interface.

We see this pattern in ECE351 with operator() in our compiler. The idea is that we can just call some operation() on a leaf element or a group of elements, where for a group, we call operation() for all elements in a group, but the interface is the same.

interface Graphic {
    fun draw()
}
 
class Circle : Graphic {
    override fun draw() { /* draw circle */ }
}
 
class CompositeGraphic : Graphic {
    private val children = mutableListOf<Graphic>()
    fun add(g: Graphic) { children.add(g) }
    fun remove(g: Graphic) { children.remove(g) }
    override fun draw() { children.forEach { it.draw() } }
}