0

序言:基类意识到并使用派生类型进行交互是不好的设计吗?我假设不是,那么我应该考虑以下哪种方法?


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

4

1 回答 1

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;
}

对我来说,这似乎是可以存在于外部迭代器对象中的东西,但我不能说我在发表这篇文章之前考虑了很多......

于 2011-12-12T21:07:01.843 回答