PHP Objects, Patterns and Practice (3rd edition)

(Barry) #1

■Chapter 10: Patterns for Flexible Object Programming...............................................................


The Composite pattern is a simple way of aggregating and then managing groups of similar objects so
that an individual object is indistinguishable to a client from a collection of objects. The pattern is, in fact,
very simple, but it is also often confusing. One reason for this is the similarity in structure of the classes in
the pattern to the organization of its objects. Inheritance hierarchies are trees, beginning with the super
class at the root, and branching out into specialized subclasses. The inheritance tree of classes laid down by
the Composite pattern is designed to allow the easy generation and traversal of a tree of objects.
If you are not already familiar with this pattern, you have every right to feel confused at this point.
Let’s try an analogy to illustrate the way that single entities can be treated in the same way as collections
of things. Given broadly irreducible ingredients such as cereals and meat (or soya if you prefer), we can
make a food product—a sausage, for example. We then act on the result as a single entity. Just as we eat,
cook, buy, or sell meat, we can eat, cook, buy, or sell the sausage that the meat in part composes. We
might take the sausage and combine it with the other composite ingredients to make a pie, thereby
rolling a composite into a larger composite. We behave in the same way to the collection as we do to the
parts. The Composite pattern helps us to model this relationship between collections and components
in our code.


The Problem


Managing groups of objects can be quite a complex task, especially if the objects in question might also
contain objects of their own. This kind of problem is very common in coding. Think of invoices, with line
items that summarize additional products or services, or things-to-do lists with items that themselves
contain multiple subtasks. In content management, we can’t move for trees of sections, pages, articles,
media components. Managing these structures from the outside can quickly become daunting.
Let’s return to a previous scenario. I am designing a system based on a game called Civilization. A
player can move units around hundreds of tiles that make up a map. Individual counters can be grouped
together to move, fight, and defend themselves as a unit. Here I define a couple of unit types:


abstract class Unit {
abstract function bombardStrength();
}


class Archer extends Unit {
function bombardStrength() {
return 4;
}
}


class LaserCannonUnit extends Unit {
function bombardStrength() {
return 44;
}
}


The Unit class defines an abstract bombardStrength() method, which sets the attack strength of a
unit bombarding an adjacent tile. I implement this in both the Archer and LaserCannonUnit classes.
These classes would also contain information about movement and defensive capabilities, but I’ll keep
things simple. I could define a separate class to group units together like this:


class Army {
private $units = array();


function addUnit( Unit $unit ) {
array_push( $this->units, $unit );
}

Free download pdf