深入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)
    {
        $this->units = array_udiff($this->units, array($unit), function ($a, $b) {
            return ($a === $b) ? 0 : 1;
        });
    }

    function bombardStrength()
    {
        $ret = 0;
        foreach ($this->units as $unit) {
            $ret += $unit->bombardStrength();
        }
        return $ret;
    }

}

实际上,我们并不希望在Archer对中添加Unit对象,我们可以修改之前设计的代码,在Unit类的addUnit()/removeUnit()方法中抛出异常:

class UnitException extends Exception{};
abstract class 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");
    }

    abstract function bombardStrength();
}

这样做可以出去局部类中的重复代码,但是同时组合类不再需要强制地实现和两个方法,这可能会带来问题。

我们先回顾一下组合模式带来的益处:

  • 灵活:因为组合模式中的一切类型都共享一个父类型,所以可以轻松地在设计中添加新的组合对象或者局部对象,而无需大范围地修改代码。
  • 简单:使用组合结构的客户端代码只需要设计简单的接口。
  • 隐式到达:组合模式中的对象通过树形结构组织。
  • 显式到达:树形结构可以轻松遍历。

我们将add/remove方法降到下一级对象中,以便这些方法仅在组合类中使用:

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 addUnit(Unit $unit)
    {
        if (in_array($unit, $this->units, true)) {
            return;
        }
        $this->units[] = $unit;
    }

    function removeUnit(Unit $unit)
    {
        $this->units = array_udiff($this->units, array($unit), function ($a, $b) {
            return ($a === $b) ? 0 : 1;
        });
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值