output:
Army Object
(
[units:Army:private] => Array
(
[0] => Soldier Object
(
)
[1] => Tank Object
(
)
[2] => Tank Object
(
)
)
)
16
Army Object
(
[units:Army:private] => Array
(
[1] => Tank Object
(
)
[2] => Tank Object
(
)
)
)
8
添加异常处理
<?php
abstract class Unit {
abstract function addUnit( Unit $unit );
abstract function removeUnit( Unit $unit );
abstract function bombardStrength();
}
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 ) {
// >= 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 bombardStrength() {
$ret = 0;
foreach( $this->units as $unit ) {
$ret += $unit->bombardStrength();
}
return $ret;
}
}
class UnitException extends Exception {}
class Archer extends Unit {
function addUnit( Unit $unit ) {
throw new UnitException( get_class($this)." is a leaf" );
}
function removeUnit( Unit $unit ) {
throw new UnitException( get_class($this)." is a leaf" );
}
function bombardStrength() {
return 4;
}
}
$archer = new Archer();
$archer2 = new Archer();
$archer->addUnit( $archer2 );
?>
output:
Fatal error: Uncaught exception 'UnitException' with message 'Archer is a leaf'
点评:组合模式中的一切类都共享同一个父类型,可以轻松地在设计中添加新的组合对象或局部对象,而无需大范围地修改代码。
最终的效果,逐步优化(完美):
<?php
class UnitException extends Exception {}
abstract class Unit {
abstract function bombardStrength();
function addUnit( Unit $unit ) {
throw new UnitException( get_class($this)." is a leaf" );
}
function removeUnit( Unit $unit ) {
throw new UnitException( get_class($this)." is a leaf" );
}
}
class Archer extends Unit {
function bombardStrength() {
return 4;
}
}
class LaserCannonUnit extends Unit {
function bombardStrength() {
return 44;
}
}
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 ) {
// >= 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 bombardStrength() {
$ret = 0;
foreach( $this->units as $unit ) {
$ret += $unit->bombardStrength();
}
return $ret;
}
}
// create an army
$main_army = new Army();
// add some units
$main_army->addUnit( new Archer() );
$main_army->addUnit( new LaserCannonUnit() );
// create a new army
$sub_army = new Army();
// add some units
$sub_army->addUnit( new Archer() );
$sub_army->addUnit( new Archer() );
$sub_army->addUnit( new Archer() );
// add the second army to the first
$main_army->addUnit( $sub_army );
// all the calculations handled behind the scenes
print "attacking with strength: {$main_army->bombardStrength()}n";
?>







