PHP Objects, Patterns and Practice (3rd edition)

(Barry) #1
CHAPTER 10 ■ PATTERNS FOR FLEXIBLE OBJECT PROGRAMMING

Figure 10–2. Moving add/remove methods out of the base class


The annoying, useless implementations of add/remove methods in the leaf classes are gone, but the
client must still check to see whether it has a CompositeUnit before it can use addUnit().
This is where the getComposite() method comes into its own. By default, this method returns a null
value. Only in a CompositeUnit class does it return CompositeUnit. So if a call to this method returns an
object, we should be able to call addUnit() on it. Here’s a client that uses this technique:


class UnitScript {
static function joinExisting( Unit $newUnit,
Unit $occupyingUnit ) {
$comp;


if (! is_null( $comp = $occupyingUnit->getComposite() ) ) {
$comp->addUnit( $newUnit );
} else {
$comp = new Army();
$comp->addUnit( $occupyingUnit );
$comp->addUnit( $newUnit );
}
return $comp;
}
}


The joinExisting() method accepts two Unit objects. The first is a newcomer to a tile, and the
second is a prior occupier. If the second Unit is a CompositeUnit, then the first will attempt to join it. If
not, then a new Army will be created to cover both units. I have no way of knowing at first whether the
$occupyingUnit argument contains a CompositeUnit. A call to getComposite() settles the matter, though.
If getComposite() returns an object, I can add the new Unit object to it directly. If not, I create the new
Army object and add both.
I could simplify this model further by having the Unit::getComposite() method return an Army
object prepopulated with the current Unit. Or I could return to the previous model (which did not
distinguish structurally between composite and leaf objects) and have Unit::addUnit() do the same
thing: create an Army object, and add both Unit objects to it. This is neat, but it presupposes that you
know in advance the type of composite you would like to use to aggregate your units. Your business logic

Free download pdf