对象模型设计;基类对派生类的认识

时间:2011-12-12 20:52:35

标签: php design-patterns inheritance derived-class tree-traversal

序言:基类知道并使用派生类型进行交互是不是很糟糕?我假设没有,那么我应该考虑以下哪种方法?


语言是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

1 个答案:

答案 0 :(得分:1)

你应该能够概括它:

public function get_ancestor($type){
    if($this->_parent instanceof $type){
        return $this->_parent;
    }
    if(null !== $this->_parent){
        return $this->_parent->get_ancestor($type);
    }
    return null;
}

对我而言,似乎这可能存在于外部迭代器对象中,但我不能说在做这篇文章之前我已经做了很多考虑......