PHP设计模式之组合模式

你还记得“组合优于继承”这个设计原则吗?该原则体现了类和对象之间的组织弹性。为了使项目更具灵活性,我们需要将类按一定结构组织起来,以便它们的对象在代码运行时能被构造为有用的结构。

下面我们来介绍组合模式,将一组对象组合为可像单一对象一样被使用的结构,这是组合模式的原则。好比是一棵树,有枝有叶,但是你使用的时候拿起的是一条有枝有叶的枝干。组合模式便是枝叶组合的过程。

例子是这样的,一个很老的例子。玩家可以在地图上组成战斗单元(Unit),战斗单元上有弓箭手(Archer)和激光炮(LaserCannonUnit),战斗单元能组成独立战斗单元-军队(Army)。独立战斗单元之间能够合并新的战斗单元,而战斗单元只能添加。

<?php

/**
 * 基础单元
 * Class Unit
 */
abstract class Unit {
    function getComposite() {
        return null;
    }

    /**
     * 获得战力
     * @return mixed
     */
    abstract function bombardStrength();
}

/**
 * 上层单元
 * Class CompositeUnit
 */
abstract class CompositeUnit extends Unit {
    protected $units = array();
    function getComposite() {
        return $this;
    }
    protected function units() {
        return $this->units;
    }
    function removeUnit( Unit $unit ) {
        $this->units = array_udiff( $this->units, array( $unit ),
                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
 */
class Army extends CompositeUnit {
    function bombardStrength() {
        $ret = 0;
        foreach( $this->units as $unit ) {
            $ret += $unit->bombardStrength();
        }
        return $ret;
    }
}

/**
 * 弓箭手
 * Class Archer
 */
class Archer extends Unit {
    function bombardStrength() {
        return 4;
    }
}

/**
 * 激光炮
 * Class LaserCannonUnit
 */
class LaserCannonUnit extends Unit {
    function bombardStrength() {
        return 44;
    }
}

/**
 * 军队合成器
 * Class UnitScript
 */
class UnitScript {
    static function joinExisting( Unit $newUnit, Unit $occupyingUnit ) {
        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->bombardStrength() );

如果你想像对待单个对象一样对待组合对象,那么组合模式十分有用。因为组合模式是树状的结构,所以对整体的操作会影响到局部,而通过组合,对客户端代码来说局部的数据有时透明的。

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇