【问题标题】:How to properly create two entities with cyclic dependency?如何正确创建两个具有循环依赖的实体?
【发布时间】:2010-11-12 09:15:29
【问题描述】:

如果我有两个实体,ParentChildParent 需要了解其所有 Child 子级,并且每个 Child 实例都需要了解其父级 Parent 实例,如何我应该正确地做到这一点(就 DDD 等而言)?

简单的方法是parent.addChild(new Child(parent)),但这看起来很丑 - 以及:

parent.addChild(new Child()); // Then call some setParent method on child, which needs to be public

我需要在这里使用工厂吗?如果有,怎么做?

谢谢

【问题讨论】:

    标签: oop design-patterns domain-driven-design


    【解决方案1】:

    一种选择是在 Parent 类上有一个相关的实例方法。此处可能不需要静态工厂,因为您正在对现有对象进行操作并且只需要将对象与另一个对象连接即可。

    public class Parent {
    
        // ...
    
        public Child createChild() {
            Child c = new Child(this);
            this.addChild(c);
            return c;
        }
    
        protected void addChild(c) {
            // ...
        }
    
        // ...
    
    }
    
    public class Child {
    
        public Child(Parent p) {
            // ...
            this.addParent(p);
        }
    
        protected addParent(Parent p) {
            // ...
        }
    }
    

    如果 Child 构造函数需要参数,您可以将这些参数传递给 createChild 方法。

    【讨论】:

    • 是的,但这仍然会将“父设置器”暴露给任何其他想要创建子对象的对象。我的观点是只有父母才能设置孩子的父母。这是不合理的要求吗?还是会增加太多开销/复杂性?
    • @Piotr:这就是你需要让父母和孩子更深入地了解彼此的时候。在 Java 中,您可以通过将它们放在同一个包中来做到这一点。在 C++ 中,他们只能通过朋友访问彼此。 (我知道 C# 中必须有一个等价物,但我不知道。)
    • 如果您的目标是隐藏父设置器,您可以使用类似 SWT 的基于构造函数的子创建。
    • @Donal Fellows 很重要。也许我应该考虑将它们放在同一个包中。感谢您的输入
    • @Piotr Blasiak:在这种情况下,您需要将父级传递给子级的构造函数,并将“addParent”方法的可见性更改为受保护或私有。我更新了我的示例。
    【解决方案2】:

    您不仅限于一种方法。您应该使用适合您的方法。

    在 SWT 中,子级在构造函数中链接到父级:

    new Label(parentComposite, SWT.NONE);
    

    在那个 parentComposite 知道它的孩子之后。

    注意:SWT 在创建时需要父级,这会限制某些功能 - 如果不指定子级,则无法创建子级。这是 SWT 的限制。

    在 Swing 中,您可以创建子小部件,然后将其添加到父小部件。

    以上只是示例。您的个人解决方案将基于您的需求。

    我会考虑使用更少的方法,更多的一致性(不要让您的孩子与父母断开联系)

    谈到代码我会使用以下方法:

    Parent {
     addChild(Child child) {
      children.add(child);
      child.setParent(this);
     }
    }
    

    希望对您有所帮助。设计愉快!

    【讨论】:

    • 感谢您的回答,能否请您检查一下 Sauls 的回答以及我对此的评论和评论?
    【解决方案3】:

    如何做这样的事情:

    public class Child {
       Child (Parent parent) {
          ... 
          this.parent = parent;
          parent.addChild(this);
       }
    }
    

    因此您只能在创建子节点时将父节点设置为子节点。

    【讨论】:

      猜你喜欢
      • 2021-08-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-23
      • 1970-01-01
      • 2017-02-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多