代码之家  ›  专栏  ›  技术社区  ›  RolandTumble

OO设计问题-父/子(ren)-循环?

  •  15
  • RolandTumble  · 技术社区  · 15 年前

    我对OO设计过程相当陌生,所以请容忍我。。。。

    我需要将两个实体建模为类,称它们为父实体和子实体(这与实际的问题域非常接近)。一位家长将有一个或多个孩子——在本申请中,我对无子女家长不感兴趣。

    我的大脑去哪里吃午饭是基于这样一个事实,即我需要能够从另一个中找到其中的一个。在我的数据库中,我可以用一个普通的外键关系来实现这一点,而SQL基于集合的特性使查找给定父级的所有子级或给定子级的父级变得很容易。但是作为物体。。。?

    认为

    我是:

    • 完全偏离了基地?如果是,我应该做什么不同的事情?

    这几乎肯定会在VB.NET中实现,但我还不知道如何裁剪代码。

    在8个答案后编辑:

    澄清回答中提出的两个问题:

    • 一点关系也没有。我选择了 我之所以这么做是因为他们 非常接近真实世界 问题域,现在看到它是 态度
    • 层次结构只有一层——子级永远不会有子级

    再次感谢。

    8 回复  |  直到 15 年前
        1
  •  11
  •   John Kugelman Michael Hodel    15 年前

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

    interface Node {
        // ...
        readonly attribute Node     parentNode;
        readonly attribute NodeList childNodes;
        // ...
    }
    
        2
  •  8
  •   womp    15 年前

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

    诸如Lightspeed或Microsoft的Entity Framework之类的ORM工具通常使用“延迟加载”指令来处理此问题。它们将首先获取您需要的内容(因此,当您获取子对象时,它只获取子属性和父对象的ID)。如果稍后取消对父对象的引用,它将获取父属性并实例化父对象。如果以后仍然访问它的子对象集合,它将获取相关的子信息并为该集合创建子对象。但是,在您需要它们之前,它不会填充它。

        3
  •  2
  •   Robert    15 年前

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

        4
  •  2
  •   Paul Sonier    15 年前

    Parent 提及其子女,以及 Child 有对其父代的引用吗?

        5
  •  2
  •   Randolpho    15 年前

    你是说一个类层次结构,父类知道它的子类吗?

    你应该不惜一切代价避免这种情况。

    默认情况下,子类了解父类的所有信息, 因为它是父类的实例 . 但要让父类了解其子类,子类还需要了解所有其他子类。这将在该类的一个子级和其他每个子级之间创建依赖关系。这是一个无法维护的场景 将来会出现问题——如果您甚至可以让它编译或运行,在许多语言中都不会出现这种情况。

    也就是说,在我看来,您并不是在尝试创建类层次结构,而是一个集合层次结构,即树。在这种情况下,是的,你在正确的轨道上;这是一个常见的范例。父节点具有子节点的集合,子节点具有对父节点的引用。

    问题是什么?他们是 同班 ! 下面是一个非常简单的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);
      }
    }
    

    我觉得这才是你真正想要的。使用这个范例,您可以将子类节点用于任何邪恶的目的。

        6
  •  1
  •   Aiden Bell    15 年前

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

    您指定的解决方案(父级包含子级引用,反之亦然)消除了遍历树以获取给定子级和节点子级的祖先的需要。这实际上只是一棵树,你可以在它上面执行各种链接和算法来遍历和枚举它。这很好!

    我建议你读一读《树木》一章 对于一个优秀的和深入的树结构和有效的方法来列举亲子关系。

        7
  •  1
  •   Spencer Ruport    15 年前

    如果孩子们 必须 有一个父类我通常只需要在子构造函数中有一个父类实例。

        8
  •  0
  •   Justin Niessner    15 年前

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

    更好地解释这个目标可能也会更有帮助。。。

    我多读了一点(并听取了评论)……结果证明我完全错了。循环引用确实有它们的位置,只要你小心使用它们,不要让它们失控。