Pattern: Composite


Context

Sometimes it is necessary to perform an operation on all of the nodes of a tree structure. The traditional recursive algorithm would traverse the tree by switching on the type of each node, descending deeper for composite nodes. Switching on the type of an object is not considered good practice because the code must be modified when new types are added. As a client we want to be able to perform a uniform operation on each node, regardless of whether it is a leaf or branch.

Solution

Subclass the composite class, and leaf classes, from a single common abstract class. The abstract class represents both the composite and leaf objects, allowing the programmer to treat both types of object in the same way.

The leaf object can then respond to some of the parenting messages (for example, it will respond to a 'get children' message by answering an empty collection), and the composite object responds to leaf messages by passing the message on to its children.

Example

Consider the imaginary classes Section(children) and Paragraph(text) which can be used to represent a document. A section can contain any combination of sections and paragraphs.

Document is an abstract class from which Section and Paragraph are subclassed.

Document>>children
        "Answer the children of the receiver.
        The default is to answer an empty collection.
        This is overridden by Section"

        ^OrderedCollection new

Document>>print
        "This should be overridden by concrete subclasses." 

        self subclassResponsibility

Section>>children
        "Answer the children contained by the receiver." 

        ^children

Section>>print
        "Pass the print request to each of the receivers children."

        children do: [:c | c print]

Paragraph>>print
        "Print the text of the receiver."
        ...

Related Patterns