abstract class Unit{
protected $depth = 0;
function accept(ArmyVisitor $visitor){
$method = "visit" . get_class($this);
$visitor->$method($this);
}
protected function setDepth($depth){
$this->depth = $depth;
}
function getDepth(){
return $this->depth;
}
abstract function bombardStrength();
}
//射手
class Archer extends Unit{
//轰炸强度,战斗力
function bombardStrength(){
return 2;
}
}
//骑兵
class Cavalry extends Unit{
function bombardStrength(){
return 4;
}
}
//激光大炮
class LaserCannonUnit extends Unit{
function bombardStrength(){
return 6;
}
}
//部队运输
class TroopCarrierUnit extends Unit{
function bombardStrength(){
return 18;
}
}
//组合单元
abstract class ContainerUnit extends Unit{
protected $units = [];
function addUnit(Unit $unit){
foreach($this->units as $thisUnit){
if($unit === $thisUnit){
return ;
}
}
$unit->setDepth($this->depth + 1);
$this->units[] = $unit;
}
function accept(ArmyVisitor $visitor){
$method = "visit" . get_class($this);
$visitor->$method($this);
foreach($this->units as $thisUnit){
$thisUnit->accept($visitor);
}
}
}
class Army extends ContainerUnit{
//总战斗力
function bombardStrength(){
$ret = 0;
foreach($this->units as $unit){
$ret += $unit->bombardStrength();
}
return $ret;
}
}
//军队访问者
abstract class ArmyVisitor{
abstract function visit(Unit $node);
function visitArmy(Army $node){
//调用各自子类的访问方法
$this->visit($node);
}
function visitArcher(Archer $node){
$this->visit($node);
}
function visitCavalry(Cavalry $node){
$this->visit($node);
}
function visitLaserCannonUnit(LaserCannonUnit $node){
$this->visit($node);
}
function visitTroopCarrierUnit(TroopCarrierUnit $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->bombardStrength() . "\n";
$this->text .=$ret;
/*$this->text .= $node->bombardStrength()."
";*/
/*格式如下
* Army: bombard: 30
Archer: bombard: 2
Cavalry: bombard: 4
LaserCannonUnit: bombard: 6
TroopCarrierUnit: bombard: 18*/
}
function getText(){
return $this->text;
}
}
$main_army = new Army();
$main_army->addUnit(new Archer());
$main_army->addUnit(new Cavalry());
$main_army->addUnit(new LaserCannonUnit());
$main_army->addUnit(new TroopCarrierUnit());
$text_dump_visitor = new TextDumpArmyVisitor();
$main_army->accept($text_dump_visitor);
print $text_dump_visitor->getText();
//税务官
class TaxCollectionVisitor extends ArmyVisitor{
private $due = 0;
private $report = "";
function visit(Unit $node){
$this->levy($node,1);
}
function visitArcher(Archer $node){
$this->levy($node,2);
}
function visitCavalry(Cavalry $node){
$this->levy($node,3);
}
function visitTroopCarrierUnit(TroopCarrierUnit $node){
$this->levy($node,5);
}
private function levy(Unit $unit,$amount){
$this->report .= "Tax levied for ".get_class($unit);
$this->report .= ": $amount\n";
$this->due += $amount;
}
function getReport(){
return $this->report;
}
function getTax(){
return $this->due;
}
}
$texVisitor = new TaxCollectionVisitor();
$main_army->accept($texVisitor);
print $texVisitor->getReport();