OO设计问题 - 家长/孩子(通知) - 通函?

时间:2009-06-22 19:26:05

标签: data-structures oop tree class-design

我对OO设计过程相当陌生,所以请耐心等待....

我有两个实体需要建模为类,称之为Parent和Child(它与实际问题域足够接近)。一位家长将有一个或多个孩子 - 在这个申请中,我对没有孩子的父母没有兴趣。

我的大脑出去吃午餐的事实是我需要能够找到另一个。在我的数据库中,我可以使用正常的外键关系实现它,并且SQL的基于集合的特性使得查找给定父项的所有子项或给定子项的父项变得容易。但作为对象......?

认为父母应该携带儿童的集合(列表,无论如何)。我还认为每个孩子都应该提及其父母。然而,参考文献的循环性质让我头疼。

我是:

  • 走在正确的轨道上?
  • 完全离开基地?如果是这样,我该怎么办?

这几乎肯定会在VB.NET中实现,但我还是可以通过削减代码来实现。

8个答案后编辑:

谢谢大家。很难选择一个接受的答案。

澄清答案中提出质疑的几件事:

  • 父母和孩子非常不同 实体 - 没有继承 关系。我选择了 我做的名字,因为他们是 真的非常接近现实世界 问题域,现在看到它 来自OO的混淆来源 透视图。
  • 层次结构只有一层深 - 孩子们永远不会有孩子 在申请中。

再次感谢。

8 个答案:

答案 0 :(得分:11)

创建树结构时,循环引用很好并且绝对标准。例如,HTML的文档对象模型(DOM)在DOM树中的每个node上都具有父属性和子属性:

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

答案 1 :(得分:8)

听起来你正走在正确的轨道上。根据您的域名模式,父母有子女,孩子有父母。您可能需要引用另一个。

循环引用没有任何问题,你只需要小心你用它们做什么。遇到麻烦的地方是从数据库加载实体时,以自动方式管理服务器端的实体。例如,您使用查询从数据库中获取Child对象。你是否包括父信息?你是否包括父母的孩子?

像Lightspeed或Microsoft的Entity Framework这样的ORM工具通常使用“延迟加载”指令来处理这个问题。他们会首先获取您需要的内容(因此,当您获取Child时,它只会获取Child属性和父级ID)。如果稍后,您取消引用Parent,它将获取Parent属性并实例化Parent对象。如果以后仍然访问它的Children集合,则它会获取相关的子信息并为该集合创建Child对象。直到你需要它们为止,它不会填充它。

答案 2 :(得分: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);
  }
}

我有一种感觉,这就是你真正追求的。使用这个范例,您可以将Node子类化为您可能具有的任何恶意目的。

答案 3 :(得分:2)

我认为能够以这种方式遍历对象图是合理的。很难从你的帖子中知道你是否有合理的理由,但我认为这些参考资料本身并不是一个糟糕的设计。

答案 4 :(得分:2)

我相信你走的正确。为什么引用的循环性质使你的头部受伤? Parent引用其子代的基本问题是什么,Child引用其父代的问题是什么?

答案 5 :(得分:1)

如果我理解P的对象包含代表孩子的对象数组P-> c []。任何没有孩子的节点P都是叶子......每个P包含P-> P'(父母)。

您指定的解决方案,其中Parent包含对子项的引用,反之亦然,无需遍历树以获取给定子项和节点子项的祖先。这实际上只是一个树,你可以执行各种链接和算法来遍历和枚举它。这很好!

我建议阅读计算机程序设计艺术中的树章,深入了解树木结构和列举亲子关系的有效方法。

答案 6 :(得分:1)

如果孩子必须有父母,我通常只需要子构造函数中的父类型实例。

答案 7 :(得分:0)

听起来像你正在走向糟糕的设计之路。您的架构永远不应该有循环引用。

你应该重新检查一下你的孩子为什么需要一个回到父母的引用,反之亦然。我会倾向于有一群孩子的父母。然后,您可以向父项添加功能,以检查子对象是否是实例的子项。

更好地探索目标可能会更有帮助......

修改

我读了一些(并听取了评论)......事实证明我错了。事实上,循环引用确实有它们的位置,只要你小心它们并且不要让它们失控。