<?php
/** 抽象父类**/
abstract class Unit{
public $depth=0;
function getComposite(){
return null;
}
function textDump($num=0){
$ret="";
$pad=4*$num;
$ret.=sprintf("%{$pad}s","");
$ret.=get_class($this);
$ret.="bombard: ".$this->bombardStrength()."\n";
return $ret;
}
function accept(ArmyVisitor $visitor){
$method="visit".get_class($this);//得到类名然后再组合成ArmyVisitor下面的函数名
$visitor->$method($this);//然后再执行函数
}
protected function setDepth($depth){
$this->depth=$depth;
}
function getDepth(){
return $this->depth;
}
abstract function bombardStrength();
}
/**抽象子类继承父类**/
abstract class CompositeUnit extends Unit{
private $units=array();
function getComposite(){
return $this;
}
protected function units(){
return $this->units;
}
function textDump($num=0){
$ret=parent::textDump($num);
foreach($this->units as $unit){
$ret.=$unit->textDump($num+1);
}
return $ret;
}
function removeUnit(Unit $unit){
foreach($this->units as $key=>$val){
if($unit==$val){
unset($this->units[$key]);
}
}
return $this->units;
}
function addUnit(Unit $unit){
foreach($this->units as $thisunit){
if($unit===$thisunit){
return;
}
}
$unit->setDepth($this->depth+1);//在添加实例时运行setDepth()函数确实子类深度
$this->units[]=$unit;
}
function accept(ArmyVisitor $visitor){
parent::accept($visitor);
foreach( $this->units as $thisunit){//历遍类,再调用类里面的accept()函数
$thisunit->accept($visitor);
}
}
}
class Archer extends Unit{
function bombardStrength(){
return 10;
}
}
class LaserCannon extends Unit{
function bombardStrength(){
return 20;
}
}
class Cavalry extends Unit{
function bombardStrength(){
return 30;
}
}
class TroopCarrier extends CompositeUnit{
function bombardStrength(){
$ret=0;
/*数组里面是对象,那循环输出时就要加()*/
foreach($this->units() as $unit){
$ret+=$unit->bombardStrength();
}
return $ret;
}
}
class Army extends CompositeUnit{
function bombardStrength(){
$ret=0;
foreach($this->units() as $unit){
$ret+=$unit->bombardStrength();
}
return $ret;
}
}
//抽象的组合类
abstract class ArmyVisitor{
abstract function visit(Unit $node);
function visitArcher(Archer $node){
$this->visit($node);
}
function visitCavalry(Cavalry $node){
$this->visit($node);
}
function visitLaserCannon(LaserCannon $node){
$this->visit($node);
}
function visitTroopCarrier(TroopCarrier $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.=get_class($node).": ";
$ret.="bombard:".$node->bombardStrength()."<br>";
$this->text.=$ret;
}
function getText(){
return $this->text;
}
}
//税率类,每个观察者的税率
class TaxCollectionVisitor extends ArmyVisitor{
private $due=0;
private $report="";
function visit(Unit $node){
$this->levy($node,1);
}
function visitCavalry(Cavalry $node){
$this->levy($node,2);
}
function visitArcher(Archer $node){
$this->levy($node,2);
}
function visitTroopCarrier(TroopCarrier $node){
$this->levy($node,3);
}
function visitLaserCannon(LaserCannon $node){
$this->levy($node,2.5);
}
private function levy(Unit $unit,$amount){
$this->report .="征收税率为:".get_class($unit);
$this->report .=": $amount <br>";
$this->due+=$amount;
}
function getReport(){
return $this->report;
}
function getTax(){
return $this->due;
}
}
/**这个类是用来调用实例化的,也可以不用写这个类,自己直接调用**/
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;
}
}
$main=new Army();
$main->addUnit(new Archer());
$main->addUnit(new LaserCannon());
$main->addUnit(new Cavalry());
$text=new TaxCollectionVisitor();
$main->accept($text);
echo "税率合计: ";
echo $text->getTax();
echo "<br>";
echo $text->getReport();
?>