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
Мне кажется, что ты на пути к плохому дизайну. Ваша архитектура никогда не должна иметь круглых ссылок.
Вероятно, вам следует пересмотреть, почему вашим детям нужна ссылка на родителя и наоборот. Я склонялся к родителям, имеющим коллекцию детей. Затем вы можете добавить функциональность родительскому лицу, чтобы проверить, является ли дочерний объект дочерним по отношению к экземпляру.
Лучшее объяснение цели может быть немного более полезным...
ИЗМЕНИТЬ
Я прочитал еще немного (и слушал комментарии)... и оказывается, я совсем не прав. Циркулярные ссылки действительно имеют свое место, пока вы осторожны с ними и не позволяете им выйти из-под контроля.