UMl类
代码实现
<?php //visitor.php 访问者模式 abstract class Unit{ protected $depth; function accept(ArmyVisitor $visitor){ $method = "visit".get_class($this); $visitor->$method($this); } protected function setDepth($depth){ $this->depth = $depth; } function getDepth(){ return $this->depth; } function getComposite(){ return null; } abstract function bombardStrengrg(); } abstract class CompositeUnit extends Unit{ protected $unit = array(); function getComposite(){ return $this; } function removeUnit(Unit $unit){ $this->unit = array_udiff($this->unit,array($unit), function($a,$b){return ($a===$b)?0:1;}); } function addUnit(Unit $unit){ if(in_array($unit,$this->unit,true)){ return; } $unit->setDepth($this->depth+1); $this->unit[] = $unit; } function accept(ArmyVisitor $visitor){ parent::accept($visitor); foreach ($this->unit as $thisunit) { $thisunit->accept($visitor); } } } class Army extends CompositeUnit{ function bombardStrengrg(){ $ret = 0; foreach ($this->unit as $unit) { $ret+=$unit->bombardStrengrg(); } return $ret; } } class Archer extends Unit{ function bombardStrengrg(){ return 4; } } class LaserCannon extends Unit{ function bombardStrengrg(){ return 5; } } abstract class ArmyVisitor{ abstract function visit(Unit $node); function visitArcher(Archer $node){ $this->visit($node); } function visitLaserCannon(LaserCannon $node){ $this->visit($node); } function visitTroopCarrierUnit(TroopCarrierUnit $node){ $this->visit($node); } function visitArmy(Army $node){ $this->visit($node); } } 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->bombardStrengrg()."<br>"; $this->text.=$ret; } function getText(){ return $this->text; } } class TaxCollectionVisitor extends ArmyVisitor{ private $due=0; private $report=0; function visit(Unit $node){ $this->levy($node,1); } function visitArcher(Archer $node){ $this->levy($node,2); } function visitTroopCarrierUnit(TroopCarrierUnit $node){ $this->levy($node,2); } function visitLaserCannon(LaserCannon $node){ $this->levy($node,2); } function levy(Unit $unit,$amout){ $this->report.="Tax levied for ".get_class($unit); $this->report.=": $amout<br>"; $this->due+=$amout; } function getRepost(){ return $this->report; } function getTax(){ return $this->due; } } $main_army = new Army(); $main_army->addUnit(new Archer()); $main_army->addUnit(new LaserCannon()); //$textdump = new TextDumpArmyVisitor(); $taxcollector = new TaxCollectionVisitor(); $main_army->accept($taxcollector); //echo $textdump->getText(); echo "TOTAL: "; echo $taxcollector->getTax()."<br>"; echo $taxcollector->getRepost(); ?>
问题
访问者可可以用于任何对象集合
外部化操作可能破坏封装,例如给TextdumpArmyVisitor对象提供信息,我们被迫给Unit接口提供了一个额外的方法