<?php
/*
?* WEB开发笔记 www.chhua.com 每日练习 PHP设计模式构建类和对象方法(组合模式)
?* 组合模式其实就如同大树一样,有树干(基类)、树枝(又称组合对象,继承于基类),树叶(又称局部对象,没有组合对象的组合方法)
?*/

/*废话不想多说,只想用代码演示
?* 例如:一个国家的军事力量计算,就是由一支支的军队的战斗力组成,军队又由士兵的战斗力组成。假设,要发生一场战争,那么会有很多的军队参与战争,然后在战争的过程中也许会有军队增缓,由于战争需要,也许会有军队撤出。
?*
?* 以上的模拟例子中,总军队是树干(基类),支队是树枝(是组合对象),士兵是树叶(局部对象)。
?* 所有的军队继承于总军队,并且均有计算军队撤退和支缓的功能,而士兵只有战斗力,没有这个功能。
?* 看演示。
?* */

abstract class Unit {//总军模型
?abstract function addUnit(Unit $unit);//有军队加入的方法
?abstract function removeUnit(Unit $unit);//有军队退出的方法
?abstract function getGongjili();//获取功击能力方法
}

class Army extends Unit{//军队
?private $units= array();//保存支队实例
?
?function addUnit(Unit $unit){//增加实例
??if (in_array($unit,$this->units,true)) return ;
??$this->units[]=$unit;
?}
?
?function removeUnit(Unit $unit){//移除相关的实例
??$units=array();
??foreach ($this->units as $thisunits){
???if ($thisunits!==$unit){
????$units[]=$thisunits;
???}
??}
??$this->units=$units;
?}
?
?function getGongjili(){//获取功击力
??$ret=0;
??foreach ($this->units as $unit){
???$ret+=$unit->getGongjili();
??}
??return $ret;
?}
}

class Archer extends Unit{//士兵类
?function addUnit(Unit $unit){//不能增加军队
??throw new Exception(get_class($this).”is a archer”);
?}
?
?function removeUnit(Unit $unit){//不能移除军队
??throw new Exception(get_class($this).”is a archer”);
?}
?
?function getGongjili(){
??return 10;
?}
}

$mainArmy=new Army();//创建主军队
$mainArmy->addUnit(new Archer());//添加士兵进去+10

$subArmy=new Army();//创建支军队
$subArmy->addUnit(new Archer());//添加士兵进去+10
$subArmy->addUnit(new Archer());//添加士兵进去+10

$mainArmy->addUnit($subArmy);//把分军队加入到主军中去+20

echo $mainArmy->getGongjili();//输出主军队的功击强度 为 30

$mainArmy->removeUnit($subArmy);//把支军队撤出主军队-20

echo $mainArmy->getGongjili();//再次输出主军队力量 为10
?>