如果物品知道容器,为什么不好?复合模式(2个对象互相引用)php

时间:2016-07-16 11:09:09

标签: php

当对象具有循环引用时,他们说这不是一个好主意。让我们看一个复合的例子:

class Book
{
    private $title;

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

    public function getTitle()
    {
        return $this->title;
    }
}

class Shelf
{
    private $books = [];

    public function addBook (Book $book)
    {
         $this->books[] = $book;
    }
}

$shelf = new Shelf();
$sehlf->add (new Book('a'));
$sehlf->add (new Book('b'));
$sehlf->add (new Book('c'));
到目前为止一切顺利。出于某种原因,Book必须知道Shelf,所以我重写:

class Book
{
    private $title;
    private $shelf;

    public function __construct($title, $shelf)
    {
         $this->shelf = $shelf;
         $this->title = $title;
    }

    public function getTitle()
    {
        return $this->title;
    }
}

class Shelf
{
    private $books = [];

    public function addBook (Book $book)
    {
         $this->books[] = $book;
    }
}

$shelf = new Shelf();
$sehlf->add (new Book('a', $shelf));
$sehlf->add (new Book('b', $shelf));
$sehlf->add (new Book('c', $shelf));

他们说不好。

1 个答案:

答案 0 :(得分:2)

循环引用存在一些问题,可能是found here,但我必须接受以上不是一个非常有问题的例子 - 因为很明显,必须先在书籍之前创建书架。

例如,最常见的问题之一是,如果假设变量是公共的,那么在print_r的实例上使用Book可能是“不可能的” - 会导致内存耗尽。

有几种方法可以解决循环引用问题,其中一种最常见的问题包括使用Setter injection。 e.g。

public function setShelf(Shelf $shelf)
{
    $this->shelf = $shelf;
}

PHP特有的另一个问题是它可能有解决循环依赖的问题。请参阅this for example

class Node {
    public $parentNode;
    public $childNodes = array();
    function Node() {
        $this->nodeValue = str_repeat('0123456789', 128);
    }
    function destroy()
    {
        $this->parentNode = null;
        $this->childNodes = array();
    }
}
function createRelationship() {
    $parent = new Node();
    $child = new Node();
    $parent->childNodes[] = $child;
    $child->parentNode = $parent;
    $parent->destroy();
}

PHP将最终分配大约35MB的内存,没有充分的理由。要解决这个问题,我们可以使用析构函数,以便垃圾收集器知道如何在完成对象后处理对象。

function destroy()
{
    $this->parentNode = null;
    $this->childNodes = array();
}