OO Design Question - Parent/Child (ren) - Циркуляр?

Я новичок в процессе проектирования OO, поэтому, пожалуйста, несите меня....

У меня есть два объекта, которые мне нужно моделировать как классы, называть их "Родительский и дочерний" (он достаточно близко к фактическому проблемному домену). У одного родителя будет один или несколько детей - я не заинтересован в этом заявлении в бездетных родителях.

Где мой мозг выходит на обед, это факт, что мне нужно найти друг друга. В моей базе данных я могу реализовать это с нормальным отношением внешних ключей, а основанный на наборах характер SQL позволяет легко найти всех детей для данного родителя или родителя для данного ребенка. Но как объекты...?

Я думаю, что Родитель должен нести коллекцию (список, что угодно) детей. Я также считаю, что каждый ребенок должен иметь ссылку на своего Родитель. Круговой характер ссылок, однако, заставляет мою голову болеть.

Am I:

  • На правильном пути?
  • Полностью от основания? Если да, что мне делать по-другому?

Это почти наверняка будет реализовано в VB.NET, но я пока еще не умею вырезать код.

Изменить после 8 ответов:

Спасибо всем. Было трудно выбрать только один ответ, чтобы принять.

Чтобы прояснить пару вопросов, которые были заданы в ответах:

  • Родитель и ребенок очень разные объекты - там нет наследования отношения вообще. Я выбрал имена, которые я сделал, потому что они действительно очень близко к реальному миру и теперь видим, что это источник замешательства от OO перспектива.
  • Иерархия только на один уровень - у детей никогда не будет детей в приложении.

Еще раз спасибо.

Ответы

Ответ 1

Круглые ссылки являются точными и абсолютно стандартными при создании древовидной структуры. Например, объектная модель документа HTML (DOM) имеет родительские и дочерние свойства на каждом node в дереве DOM:

interface Node {
    // ...
    readonly attribute Node     parentNode;
    readonly attribute NodeList childNodes;
    // ...
}

Ответ 2

Похоже, ты на правильном пути. Согласно вашей модели домена, родители имеют детей, а дети имеют родителей. Возможно, вам придется ссылаться друг на друга.

В циркулярных ссылках нет ничего плохого, вам просто нужно быть осторожным в том, что вы с ними делаете. Там, где вы столкнулись с проблемой, вы управляете своими сущностями на стороне сервера автоматическим способом, когда вы загружаете их из базы данных. Например, вы получаете объект Child из базы данных с запросом. Вы включаете родительскую информацию? Вы включаете родительские дети?

Инструменты ORM, такие как Lightspeed или Microsoft Entity Framework, обычно имеют дело с этим, используя директивы "ленивая загрузка". Сначала они получат то, что вам нужно (так, когда вы берете ребенка, он просто получает свойства Child и родительский идентификатор). Если позже вы разыгрываете родительский элемент, он выводит и извлекает свойства родителя и создает объект родительского объекта. Если в дальнейшем вы получите доступ к коллекции Children, он затем отправит и доставит соответствующую дочернюю информацию и создаст дочерние объекты для этой коллекции. Пока вы им не нужны, он не заполняет его.

Ответ 3

Я думаю, что разумно хотеть, чтобы таким образом можно было пересечь граф объектов. Трудно узнать, есть ли у вас обоснованная причина этого из вашего поста, но я не думаю, что ссылки сами по себе доказывают плохой дизайн.

Ответ 4

Я считаю, что ты на правильном пути. Почему круговая природа ссылок заставляет вашу голову болеть? Какова основная проблема, с которой вы столкнулись с Parent, имеющей ссылки на ее дочерние элементы, и Child со ссылкой на ее родительский элемент?

Ответ 5

Если я понимаю, что объекты P содержат массив объектов P- > c [], представляющих детей. И любой node P без детей - это лист... с каждым P, содержащим P- > P '(родительский).

Определяемое вами решение с родителями, содержащими ссылки на дочерние элементы и наоборот, устраняет необходимость прохождения дерева для получения родословной данного ребенка и дочерних элементов node. Это действительно просто дерево, в котором вы можете выполнять все виды ссылок и алгоритмы, чтобы перемещаться и перечислять его. Это нормально!

Я предлагаю прочитать главу деревьев в Искусство компьютерного программирования для отличного и углубленного изучения древовидных структур и эффективных способов перечисления родительских прав и детей.

Ответ 6

Вы говорите об иерархии классов, где родительский класс знает о своих дочерних классах?

Вы должны избегать этого любой ценой.

По умолчанию дочерний класс знает все о родительском классе, потому что это экземпляр родительского класса. Но чтобы родительский класс знал о своих дочерних классах, требуется, чтобы дочерний класс также знал все о каждом другом дочернем классе. Это создает зависимость между одним ребенком и каждым другим дочерним элементом этого класса. Это недопустимый сценарий, который вызовет проблемы в будущем - если вы даже можете его собрать или запустить, что на многих языках не будет.

Тем не менее, мне кажется, что вы не пытаетесь создать иерархию классов, а иерархию коллекции, т.е. дерево. В таком случае, да, вы на правильном пути; это общая парадигма. Родительский node имеет набор дочерних узлов, а дочерний элемент node имеет ссылку на родительский node.

Вещь? Они все одинаковые классы! Здесь очень простой пример в С#:

public class Node
{
  public readonly Node Parent; // null Parent indicates root node
  public readonly List<Node> Children = new List<Node>();
  public Node(Node parent)
  {
     Parent = parent;
  }
  public Node()
  {
     parent = null;
  }
  public void AddChild(Node node)
  {
     Children.Add(node);
  }
}

У меня такое чувство, что ты действительно на самом деле. Используя эту парадигму, вы тогда подклассом node для любых гнусных целей, которые у вас могут быть.

Ответ 7

Если у дочерних должно быть родителя, я обычно просто требую экземпляр родительского типа в дочернем конструкторе.

Ответ 8

Мне кажется, что ты на пути к плохому дизайну. Ваша архитектура никогда не должна иметь круглых ссылок.

Вероятно, вам следует пересмотреть, почему вашим детям нужна ссылка на родителя и наоборот. Я склонялся к родителям, имеющим коллекцию детей. Затем вы можете добавить функциональность родительскому лицу, чтобы проверить, является ли дочерний объект дочерним по отношению к экземпляру.

Лучшее объяснение цели может быть немного более полезным...

ИЗМЕНИТЬ

Я прочитал еще немного (и слушал комментарии)... и оказывается, я совсем не прав. Циркулярные ссылки действительно имеют свое место, пока вы осторожны с ними и не позволяете им выйти из-под контроля.