PHP OOP:流畅的界面和树形图

时间:2016-04-17 19:05:28

标签: php oop tree fluent-interface

我正在尝试为树对象创建一个流畅的界面

以下是我目前所做工作的简化示例:

<?php
class node {
    private $childs = array();
    private $parent;

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

    public function addChild($child) {
        $this->childs[] = $child;
        return $this;
    }

    public function createChild() {
        return $this->addChild(new node($this));
    }

    public function setFoo() {
        /* do something */
        return $this;
    }
}

$root = new node();

$root   ->addChild((new node($root))
            ->setFoo()
        )->addChild((new node($root))
            ->setFoo()
        );
?>

我想减少创建树的部分。 我想做的是这样的事情:

$root->createChild()->setFoo();
$root->createChild()->setFoo();

一行。而且无需显式创建新节点实例(就像我在使用new运算符的第一个代码中所做的那样)。

我的目标是能够创建任何顺序的任何树,以及任何程度的节点,而无需在代码中放置分号。

2 个答案:

答案 0 :(得分:1)

我认为您应该更改构造函数和addChild函数以始终在数据中建立父/子关系,而不是添加createChild函数。完成后,addChild函数和构造函数可用于执行您所描述的操作而无需createChild函数。现在你的构造函数允许树中不同的树和树枝之间的交叉连接,所以它可能需要改变。

class node {
    private $childs = array();
    private $parent;

    public function __construct(node $parent = null) {
        if(!is_null($parent)) {
            $parent->addChild($this);
        }
    }

    public function addChild(node $child) {
        $this->childs[] = $child;
        $child->parent = $this;
        return $this;
    }

    public function setFoo() {
        /* do something */
        return $this;
    }
}

通过这个,您可以将新对象链接到树中:

$tree = (new node())->addChild(new node())
                    ->addChild((new node())->setFoo())
                    ->addChild((new node())->addChild(new node())
                                           ->addChild(new node())
                                           ->setFoo()
                    );

尝试使用createChild函数是一种catch-22情况,有时您需要父级,有时需要子级。您可以使用包含两者的返回对象来解决它,但我认为这是一种更好避免的情况。如果你不喜欢&#34;(新节点())&#34;语法,静态函数可能是要走的路:

public static function create(node $parent = null) {
    return new node($parent);
}

根据您的口味,这可能会更漂亮一些:

$tree = node::create()->addChild(node::create())
                      ->addChild(node::create()->setFoo())
                      ->addChild(node::create()->addChild(new node())
                                               ->addChild(new node())
                                               ->setFoo()
                      );

答案 1 :(得分:0)

您可以添加此方法以尽可能创建为子项。

public function createManyChild($nbrOfChild) {
    for($i = 0; $i < $nbrOfChild; $i++){
        $this->addChild(new node($this));
    }
    return $this;
}

并使用这样的代码。

$root = new node();
$root->createManyChild(3)->setFoo();