如何在php中实现组合

时间:2016-09-01 16:49:32

标签: php oop composition

我想使用PHP实现图的下一个片段。

请参阅下面的composition example图表:

enter image description here

我们可以使用内部类在Java中实现组合。

但PHP中没有“内部类”的类比。 当然,还有一些特点。但我们可以在多个班级中使用它。

我实现了这样的构图:

class Head {
    private static $instance = NULL;

    private function __construct(){}

    public static function getInstance() {
        $traces = debug_backtrace();
        if (strcmp($traces[1]['class'], 'Human')) {
            echo "<br>Only human has head"; // Exception can be thrown here
            return NULL;
        }
        if (!static::$instance) static::$instance = new self();
        return static::$instance;
    }

    public function __toString() {
        return 'Head';
    }
}

class Human {
    private $head;

    public function __construct() {
        $this->head = Head::getInstance();
    }

    public function __toString() {
        return 'I have ' . $this->head;
    }
}

class Plant {
    private $head;

    public function __construct() {
        $this->head = Head::getInstance();
    }
}

$human = new Human();
echo $human;

$superman = new Plant();

这样做是对的吗?

有没有更好的方法在PHP中实现组合关系?

3 个答案:

答案 0 :(得分:20)

看起来你真的对OOP中的“组成”感到困惑。

组合是两个类之间的关联,其中,对于要实例化的第一个类的实例,必须为它提供第二个类。在您Human存在的特定图表中,它需要Head。在代码中它将是:

class Head {
}

class Human {
    private $head;
    public function __construct(Head $head) {
       $this->head = $head;
    }
}

$bob = new Human(new Head);

就是这样。不需要debug_backtrace(),也不需要单身反模式。而且,顺便说一句,这在Java中看起来几乎完全相同,即使有内部类的选项。

至于您发布的代码。这是错误的:

if (strcmp($traces[1]['class'], 'Human')) {
    echo "<br>Only human has head"; // Exception can be thrown here
    return NULL;
}

该图并未说明只有人才有头脑。只有人类必须具有头部才能被实例化。你也可以$skipper = new Dog(new Head);,这完全没问题。

答案 1 :(得分:3)

继承的构成。

基本上组合聚合的更强大形式。我们可以说身体和头部之间的关系是构成因为我们不能没有头部生活但是身体和手之间的关系是聚集因为我们可能失去我们的手但我们可以活着。还有较弱的关系,如直接关联临时关联

然而,依赖注入只是我们创建这些关联的模式(通过将一个类注入另一个类)。

在大多数情况下,您可以通过构造函数识别组合关系,该构造函数注入另一个对象并将其分配给其属性,对象的生命周期结束并在同一时刻开始。

除了从技术角度来看,每个协会的实施之间没有太大差异。它主要是关系定义而不是实现。

组合关系通常用于覆盖/更改或增强注入的对象类行为。不要太兴奋或担心构图。在大多数情况下,优势与继承相比很小,第三方库创建者最喜欢使用组合为其库增加额外的灵活性。

继承父类和重载/添加方法给我们提供了类似的功能,但是通过组合我们可以获得更大的灵活性。例如,如果我们的构造函数接受从Head接口继承的对象,我们可以使用HumanHead类,如果它扩展了Head接口,但我们也可以使用我们的类来增强从DogHead或DuckHead等相同接口扩展的其他生物......

这可能不是最好的例子,但它显示了基本概念。

务必查看此[Aggregation vs Composition vs Association vs Direct Association]和此[Association-Aggregation-Composition-Dependency]

答案 2 :(得分:0)

组成是两个类之间的关联,对于要实例化的第一类实例,必须为其提供第二类。在您要让人类存在的特定图表中,它需要一个头部。看下面这个例子,我只是扩展上面的例子以更好地理解。

public function test()
{
    return "I am foo";
}

class Human 
{
    public $head;

    public function __construct(Head $head)
    {
        $this->head = $head;
    }

    public function display() 
    {
        return $this->head->test();
    }
}

$obj = new Human(new Head);

echo $obj->display();