PHP OOP: свободный интерфейс и древовидные графы

Я пытаюсь создать свободный интерфейс для объектов дерева.

Вот упрощенный пример того, что я сейчас делаю:

<?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

Решение

Вместо того, чтобы добавлять функцию createChild, я думаю, что вы должны изменить свой конструктор и функции addChild, чтобы последовательно установить отношения родитель / потомок в данных. Как только вы это сделаете, функцию 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 — сложная ситуация, когда иногда вам нужен родитель, а иногда ребенок. Вы можете решить это, используя возвращаемый объект, который содержит оба, но я думаю, что лучше избегать такой ситуации. Если вам не нравится синтаксис «(new node ())», статическая функция может быть подходящим вариантом:

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

Другие решения

Вы можете добавить эти методы, чтобы создать как ребенок, как вы можете.

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

И используйте такой код.

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

По вопросам рекламы [email protected]