Преамбула : Это плохой дизайн для базового класса, чтобы знать и взаимодействовать с использованием производных типов?Я предполагаю, что нет, так какой подход я должен рассмотреть для следующего?
( Язык - это PHP, но я думаю, что этот вопрос больше касается более широкой темы шаблонов проектирования )
У меня возникла дилемма, когда я пытался смоделировать набор классов для работы в качестве узлов;Я второй раз угадываю свои дизайнерские решения, и это приводит к постоянному разочарованию.
Учитывая этот набор параметров:
- Узлы имеют родительские ссылки ( обход в одну сторону )
- Любой тип объекта, производный от Node, может быть родительским ( или дочерним ) для любого другого типа объекта, производного от Node.
Итак, у меня есть:
abstract class AbstractNode{
protected $_parent;
public function __construct(self $parent = null){
$this->_parent = $parent;
}
public function get_parent(){
return $this->_parent;
}
}
class NodeOne extends AbstractNode{ }
class NodeTwo extends AbstractNode{ }
// more derivatives
Вот здесь и возникла моя дилемма дизайна;во время обхода * может потребоваться найти NodeOne
экземпляров, самих по себе и любых других экземплярах типов, производных от AbstractNode
(, обратите внимание, что эта функциональность не является исключительной для NodeOne
экземпляров, но это только пример )
Это позволит обходить по типу, например, для агрегирования данных из объектов определенного типа вверх по дереву.Я решил специализировать метод для этой цели:
public function get_node_one_ancestor(){
if($this->_parent instanceof NodeOne){
return $this->_parent;
}
if(null !== $this->_parent){
return $this->_parent->get_node_one_ancestor();
}
return null;
}
Поскольку любой производный тип может нуждаться в обходе экземпляров NodeOne
, имеет смысл использовать этот метод в базовом классе AbstractNode
., однако теперь мой базовый класс требует знания производного типа.
Я думаю, что это плохо пахнет, но я не знаю, куда еще этот метод должен пойти.Я читаю шаблоны структурного проектирования для возможных решений.
Аналогия, которая приходит на ум, - это DOM, выполняющий обход предков для определенных типов:
<root>
<foo id="1">
<bar id="2"></bar>
<bar id="3">
<foo id="4">
<bar id="5">
<foo id="6">
<bar id="7"></bar>
</foo>
</bar>
<bar id="8"></bar>
</foo>
</bar>
</foo>
</root>