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() } }
}