PHP Patterns: The Composite Pattern
Introduction
One of the great strengths of pattern oriented design is its viral nature. That is, the way that one pattern tends to create conditions ideal for the application of another pattern, which itself then benefits from yet another. Of course, this is also one of the greatest weaknesses of the approach. Pick the wrong patterns, and you are easily beguiled into a creating a system that is poorly suited for its purpose. Assuming, though, that you select carefully, the complementary nature of many patterns can be useful. As your projects throw up design challenges, you will often find that ideal solutions are already documented in the classic pattern catalogs.
Over the next two articles, I will examine two patterns that work well together. Composite provides a mechanism for grouping multiple components together under a single interface at runtime, and Visitor is a natural way of performing operations across the resulting structure. These patterns can be used in isolation, but they are so naturally suited that they invariably end up in the kitchen together at parties.
Let's begin here with the Composite Pattern.
The Composite Pattern
Composite is a classic Gang of Four pattern. It is probably one of the most aesthetically pleasing patterns in the catalog, due to the interplay it engenders between the static inheritance structure of its components and their dynamic runtime compositional relationships. As you might expect from its name, the Composite pattern exemplifies the principle: favor composition over inheritance. As we shall see, however, inheritance does not only sit on the other side of the coin from composition, we can use inheritance relationships to promote and support composition.
Overview
The Composite pattern provides a single interface that allows a client programmer to work with single component or a collection of components interchangeably. In fact the client code may not even know whether it is manipulating one component, or many. If you are finding this hard to visualize, think of a graphical user interface. It incorporates many components: checkboxes, radio buttons, panes, windows and so on. When you move a window, you also move its contents. Although you are moving multiple components, you don't want to handle all the details yourself, like this:
$window->move();
|
It would be better to simply call move() on $window
and have the window object pass the order on to its various components. Composite
can help you to create component structures that support propagation of this kind.
The Problem
You are building an application called MyList for managing
hierarchies of notes (Note objects). Each Note
consists of a title, some text, and any number of other Note
objects. With the right interface, this could make a powerful little
utility for organizing... well, just about anything you like. Of course,
it would need specialized components to represent binary files
(Binary), Web content (WebText), and so on.
Here is a graphical representation of a set of notes:
As with the graphical user interface example, you will need to perform operations upon many components at one time. You might need to print note data, for example, and count the number of elements in a structure. Users may want to move notes around, so you should provide for this, which is simple enough, and also you should make it easy to copy parts of the structure from place to place, which is a little harder.
The Composite pattern is appropriate to a relatively clear set of conditions, all of which apply in this case.
Firstly, we want to manage components so that for core operations there
is no functional distinction between a collection of objects and a single
object. A client must be able to call the same key methods (for example,
output(), size()) on either. So you should be
able to call output() on a bunch of nested Note
objects, in exactly the same way as you are able to call output()
on a Binary object which can contain nothing but itself. In fact,
an entire collection should be functionally identical in its core interface
to a single component. This requirement should be pretty intuitive: a single
soldier attacks, as does a battalion; a boat sails, as does a flotilla. It is
natural to group items together, and then operate on the collective.
Secondly, we need to be able to select and manipulate a collection of objects
easily. A GUI, for example, might support a tear-off menu feature. A user can
pull a menu from a menu bar so that it floats as a palette. The sub-components
that make up the menu must therefore have the ability to be copied or moved
into a new context. In the MyList example, a user may want to
rearrange her notes so that a shopping list lives under 'Household' rather
than 'General' - the principle is the same.
We need an easily extensible system. Right now we know that MyList
needs a particular set of components, but we are reasonably sure that we will
add new ones in the future. We should be able to do this with minimum disruption
to our application as a whole.
The final sign that a Composite might be a suitable strategy in your code is the presence of, or a clear requirement for, a tree structure. This is in fact part of the Composite implementation, but some sets of components (GUIs, file system representations, XML elements) so obviously lend themselves to this kind of parent/child organization that the chances are you will already have thought about deploying it.
Implementation
So how do we aggregate this simplified set of components (Note,
Binary, WebText), and how do we run operations on
the resulting structure?
Apart from the client, every component in the Composite pattern belongs to the same type. This is how we can guarantee consistency across collections and individual objects - from an interface point of view there is no difference.
What can be confusing about the Composite pattern is the similarity in structure of the inheritance relationship between classes and the runtime organization of objects.
Apart from the client context, all participants extend a single, usually abstract, component class. This, of course, makes all implementing classes components themselves. The component defines methods for adding and removing other components. Implementing classes come in two flavors: the leaf, which does not accept children and the composite, which does. Figure 2 shows these participants:
Note that, according to this particular interface, both leaves and composites accept children. We will return to this issue later in the article. For now, it's worth remembering that attempting to add a component to a leaf class should result in an exception, or else silent inaction.
Here is the component superclass for the MyList example:
abstract class MyListComponent {
|
As you can see, components have two areas of responsibility. Firstly they are
concerned with adding, storing and removing other components. For this purpose
we define the add() and remove() methods. Secondly,
they must perform their core tasks as components. In this example I have defined
two operations common to all components: output() and
number(). output() is responsible for printing a very
basic text representation of the contents of a ListComponent object.
number() returns the number of components at and below the current
level in the tree.
Here is the Binary class, which is a leaf:
class Binary extends MyListComponent {
|
As is usual in example code, rigor has been sacrificed for clarity. In the real world we would apply more error checking and more sophisticated functionality. The objective here, though, is to keep things simple.
The Binary class is forced by the MyListComponent class
to implement add() and remove() methods. However, because
this class is a leaf type, those methods do not actually do anything.
Binary also implements number() to simply return
1. Since it cannot aggregate any components, it will only ever
represent itself.
The output() method prints the name of the file that the class
is designed to manage. output() is not designed for multimedia
display, so Binary gives information about the file, rather than
displaying the file itself. This method, in its various implementations, is
therefore useful mainly for information and debugging. I'll look at ways in
which presentation code might more usefully engage with our components in the
next article in this series.
Things get a little more interesting when we add a composite to the mix. As
you saw in figure 2, a composite is responsible for adding, removing and
working with child components, as well as performing its own duties. If you
have more than one composite type, it's a good idea to create an abstract
superclass that implements add() and remove(),
as these are not likely to change between composite classes.
Here is an abstract composite class:
abstract class MyListComposite extends MyListComponent {
|
There's a lot going on here, but nothing that should cause great brain ache.
Obeying the interface laid down in MyListComponent, the
add() method accepts a MyListComponent object and
adds it to the protected $children array property.
remove() reverses this, using array_search() to locate
the given element, and array_splice() to remove it. Notice the third
Boolean we pass to array_search(). This forces the search to respect
type (the equivalent of using === rather then == for
comparison).
We have add() return the MyListComponent it has been
given. This may seem redundant, but it can make for nicely compact client code.
If add() did not return a component, you would have to do this:
$list = new ConcreteMyListComposite('shopping list');
|
If add() returns its component, we can save a line of code here:
$list = new ConcreteMyListComposite('shopping list');
|
We can even chain multiple additions into a single statement:
$list->add(new ConcreteMyListComposite('bread'))->add(new ConcreteMyListComponent('bread info'));
|
number() and __clone() both show typical behavior
for composite operations. In number() we first set the return
value to 1, accounting for the current component. Then we cycle
through the $children array, calling number() on
each member. Remember that $children is guaranteed to contain
MyListComponent objects, thanks to the type hinting in the
add() method declaration. The abstract method declaration in
MyListComponent ensures that all subclasses will implement the
number() method.
__clone() is a magic method. It is automatically called by the
Zend Engine when the clone operator is used on an object. The
thing to remember about __clone() is that it works after the
fact. The $this variable in the method actually refers to the
cloned object, not to the original. The initial clone is shallow, however,
which means that all references are shared. A cloned MyListComposite
object will have its own $children array, but its members will
be references to the children that were aggregated by the original object.
This could make for some interesting bugs. We overcome the problem by cloning
all elements in the $children array. Any children that are
composites will do the same to their children, because they will inherit
this __clone() method.
Now that I have discussed __clone(), you may wish to consider
what happens when a Binary object is cloned. You will end up
with two objects pointing to the same file on disk. I will leave this problem
as an exercise for the reader.
MyListComposite is abstract because it leaves the implementation
of output() to extending classes. For example, here is a class
named Note:
class Note extends MyListComposite {
|
This simple class manages $title and $note properties.
Since it extends MyListComposite, it only needs to implement
output(). The mechanism here should be familiar by now. The
method prints data for the local class, and then loops through the
$children array, calling output() on each child element.
Notice that we call a method called pad(). This is simply a
utility operation that generates a set of spaces based on an integer argument.
We use this to generate a basic layout when printing our MyList
data. The output() method passes an incremented $level
variable to its children, so each output() invocation knows about
its relative depth. Here is pad(), which is implemented by
MyListComponent:
// MyListComponent...
|
For the sake of completeness, let's add another MyListComposite object.
WebText stores a URL and prints a crudely formatted version of its data
when output() is called. Like Note, it then calls
output() on its children:
class WebText extends MyListComposite {
|
Figure 3 shows the participants of this system.
[ continued in part 2 of PHP Patterns: The Composite Pattern ]

Comments
If the leaves inherit from the Composite class then they will have concrete implementations for managing children, which leaves don't have. The Gang of Four suggest implementing defaults for managing children in the Component class that raise exceptions, so that calling a child-management function on a leaf will raise an exception.
Are you implying this functionality is part of the view/control part of the system or is it just that your article deals only with the important functionalities to have in the collection class?
Thanks for your ideas!