序言:基类意识到并使用派生类型进行交互是不好的设计吗?我假设不是,那么我应该考虑以下哪种方法?
(语言是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>
从
bar[@id='8']
聚合所有foo
祖先id
值:
结果4 1
从
bar[@id='7']
聚合所有foo
祖先id
值:
结果6 4 1