PHP Objects, Patterns and Practice (3rd edition)

(Barry) #1
CHAPTER 11 ■ PERFORMING AND REPRESENTING TASKS

function visitTroopCarrierUnit( TroopCarrierUnit $node ) {
$this->visit( $node );
}


function visitArmy( Army $node ) {
$this->visit( $node );
}
}


So now it’s just a matter of providing implementations of ArmyVisitor, and I am ready to go. Here is
the simple text dump code reimplemented as an ArmyVisitor object:


class TextDumpArmyVisitor extends ArmyVisitor {
private $text="";


function visit( Unit $node ) {
$ret = "";
$pad = 4*$node->getDepth();
$ret .= sprintf( "%{$pad}s", "" );
$ret .= get_class($node).": ";
$ret .= "bombard: ".$node->bombardStrength()."\n";
$this->text .= $ret;
}


function getText() {
return $this->text;
}
}


Let’s look at some client code and then walk through the whole process:

$main_army = new Army();
$main_army->addUnit( new Archer() );
$main_army->addUnit( new LaserCannonUnit() );
$main_army->addUnit( new Cavalry() );


$textdump = new TextDumpArmyVisitor();
$main_army->accept( $textdump );
print $textdump->getText();


This code yields the following output:

Army: bombard: 50
Archer: bombard: 4
LaserCannonUnit: bombard: 44
Cavalry: bombard: 2


I create an Army object. Because Army is composite, it has an addUnit() method that I use to add
some more Unit objects. I then create the TextDumpArmyVisitor object. I pass this to the Army::accept().
The accept() method constructs a method call and invokes TextDumpArmyVisitor::visitArmy(). In this
case, I have provided no special handling for Army objects, so the call is passed on to the generic visit()
method. visit() has been passed a reference to the Army object. It invokes its methods (including the
newly added, getDepth(), which tells anyone who needs to know how far down the object hierarchy the
unit is) in order to generate summary data. The call to visitArmy() complete, the Army::accept()

Free download pdf