Проектирование объектной модели; осведомленность базового класса о производных классах - PullRequest
0 голосов
/ 13 декабря 2011

Преамбула : Это плохой дизайн для базового класса, чтобы знать и взаимодействовать с использованием производных типов?Я предполагаю, что нет, так какой подход я должен рассмотреть для следующего?


( Язык - это 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 Ответ

1 голос
/ 13 декабря 2011

Вы должны быть в состоянии обобщить это:

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

Мне кажется, что это нечто, что могло бы существовать во внешнем объекте итератора, но я не могу сказать, что много думал перед тем, как написать этот пост ...

...