2009-06-22 1 views
15

Я довольно новичок в процессе проектирования OO, поэтому, пожалуйста, несите меня ....OO Design Question - Parent/Child (ren) - Циркуляр?

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

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

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

Am I:

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

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

Edit после 8 ответов:

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

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

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

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

+2

Могут ли дети иметь детей, или это одноуровневая иерархия? Если он многоуровневый, вам нужно посмотреть на композитный шаблон. –

+0

Разве это не вопрос времени и пространства с хранением ссылок в узлах? Зависит от ограничений ... если пространство не является проблемой, сохранение ссылок в порядке, если у них есть целостность. –

+0

@Harper Shelby - это одноуровневый. Дети никогда не будут иметь своих детей (в этом заявлении). Хороший вопрос. – RolandTumble

ответ

11

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

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

+1 ... Хороший пример, если круговое определение не имеет значения в * некоторых * языках (... попробуйте это в C: P ...) из-за автоматического выделения –

+2

Это не круговая ссылка. – Randolpho

+0

@ Randolpho - нет кругового определения –

0

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

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

Лучше explination от цели может быть немного более полезным, а также ...

EDIT

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

+0

«Ваша архитектура никогда не должна иметь круглых ссылок». Почему бы и нет? Любопытно любопытно. –

+0

Теоретически такая циклическая ссылка может приводить к бесконечному циклу. Скажем, у вас есть код, который загружает вашего родителя, а затем загружает дочерние элементы, который снова загружает родителя, который снова загружает ребенка, а затем ... и ... –

+0

Инструменты ORM часто генерируют циклические ссылки для ассоциаций по умолчанию. Не обязательно указывает на дефект дизайна. – womp

1

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

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

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

2

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

Вам следует избегать этого любой ценой.

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

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

Дело в том, что? Они все тот же класс! Вот очень простой пример в C#:

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

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

+2

Это звучало для меня как сдерживание, а не отношение наследования. – Robert

+0

@ Robert: Я согласен, но вопросник был не очень ясен, поэтому я попросил разъяснения, затем отредактировал. – Randolpho

+0

Классы будут отличаться друг от друга. Дети (очень) не то же самое, что и родители. Но я вижу, с чего я сначала не был так понятен. – RolandTumble

8

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

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

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

2

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

2

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

+0

Я думаю, это просто тренировка всех этих лет нормализованных структур таблиц .... – RolandTumble

+3

А, да, я понимаю. Имейте в виду, что в мире SQL есть дополнительный источник данных; фактическая база данных, содержащая таблицы, которые могут быть запрошены; на уровне базы данных есть «прямая ссылка» на родителя, который используется там; в вашей структуре классов нет такой запрашиваемой справки, по которой можно искать родителей. При проектировании объектов нормализация может быть ошибкой из-за невозможности запроса данных; ссылки должны быть ясными. –

+0

какое прекрасное краткое объяснение - спасибо! – Skilldrick

1

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