一、组合模式简述
1.组合定义了一个单根继承体系,使具有不同职责的集合可以并肩工作
2.如果想像对待单个对象一样对待组合对象,那么组合模式十分有用
3.组合模式不能很好地在关系数据库中保存数据,但却非常适用于xml的持久化,这是因为xml元素通常是由树型结构的子元素组合而成的。
4.组全模式需要注意操作的成本 ,组合的方法可能会逐级调用对象树中下级分支的方法,如果一个对象树中有大量的子对象,一个简单的调用可能人导致系统崩溃(递归)
二、组合例子
1.简述:要写一些类实现计算部队战斗力,部队内可能有没的军种,不同的军种有不同的战斗力,每个军种由士兵或类似的基本单元构成,一个部队可以合并另一个部队,但一个士兵或基本单元不可以合并另一个士兵或基本单元
2.类图:
三、代码
<?php abstract class Unit {
function getComposite() {
return null;
} abstract function bombardStrength();
} abstract class CompositeUnit extends Unit {
private $units = array(); function getComposite() {
return $this;
} protected function units() {
return $this->units;
} function removeUnit( Unit $unit ) {
// >= php 5.3
//$this->units = array_udiff( $this->units, array( $unit ),
// function( $a, $b ) { return ($a === $b)?0:1; } ); // < php 5.3
$this->units = array_udiff( $this->units, array( $unit ),
create_function( '$a,$b', 'return ($a === $b)?0:1;' ) );
} function addUnit( Unit $unit ) {
if ( in_array( $unit, $this->units, true ) ) {
return;
}
$this->units[] = $unit;
}
}
class Army extends CompositeUnit { function bombardStrength() {
$ret = 0;
foreach( $this->units as $unit ) {
$ret += $unit->bombardStrength();
}
return $ret;
} } class Archer extends Unit {
function bombardStrength() {
return 4;
}
} class LaserCannonUnit extends Unit {
function bombardStrength() {
return 44;
}
} 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;
}
} $army1 = new Army();
$army1->addUnit( new Archer() );
$army1->addUnit( new Archer() ); $army2 = new Army();
$army2->addUnit( new Archer() );
$army2->addUnit( new Archer() );
$army2->addUnit( new LaserCannonUnit() ); $composite = UnitScript::joinExisting( $army2, $army1 );
print_r( $composite ); ?>
运行结果:
Army Object ( [units:CompositeUnit:private] => Array ( [0] => Archer Object ( ) [1] => Archer Object ( ) [2] => Army Object ( [units:CompositeUnit:private] => Array ( [0] => Archer Object ( ) [1] => Archer Object ( ) [2] => LaserCannonUnit Object ( ) ) ) ) )