php观察者模式,组合ArmyVisitor抽象类,用accept()方法将访问者对象传递给当前对象的所有的子元素,当前组件是一个组合体

<?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();
?>
上一篇:alert弹窗切换


下一篇:连接客户端&服务端