我想知道在处理父子关系时,以下哪项被认为是最佳做法。
1)以下示例似乎是一种常见做法,但在创建子实例时,只要未添加到父级,它就处于无效状态。这不会导致验证问题等。
public class Parent
{
private ICollection<Child> children;
public ReadOnlyCollection Children { get; }
public void AddChild(Child child)
{
child.Parent = this;
children.Add(child);
}
}
public class Child
{
internal Parent Parent
{
get;
set;
}
public Child()
{
}
}
2)下一个样本会注意孩子必须始终与其父母有关。
public class Parent
{
private ICollection<Child> children;
public ReadOnlyCollection Children { get; }
public Child CreateChild()
{
var child = new Child();
child.Parent = this;
children.Add(child);
return child;
}
}
public class Child
{
internal Parent Parent
{
get;
set;
}
internal Child()
{
}
}
3)在最后一个例子中,孩子负责与父母本身的关系。
public class Parent
{
private ICollection<Child> children;
public ReadOnlyCollection Children { get; }
public void AddChild(Child child)
{
child.Parent = this;
children.Add(child);
}
}
public class Child
{
public Parent Parent
{
get;
set;
}
public Child(Parent parent)
{
this.Parent = parent;
}
}
哪种模式被认为是最好的?我相信模式2可能是最好的,因为如果没有与父母的关系,孩子就永远不会存在。这会使它更容易,例如在实现可能执行以下操作的规范模式时:
public class ChildSpecification
{
bool IsSatisfiedBy(Child child)
{
return child.Parent.Children.Where(someCondition).Count > 0;
}
}
上述规范只有在孩子有父母的情况下才有效。
你怎么看?你知道更好的方法吗?提前致谢答案 0 :(得分:6)
我非常喜欢建议2,但我认为它错过了3中的重要内容,即如果Child
对象在没有Parent
的情况下不能存在,那么它应该需要{{1}对象在其构造函数中。此外,Parent
类上的Parent
属性应该是只读的。
所以你最终会得到类似的东西:
Child
答案 1 :(得分:1)
由于我刚刚遇到相同的设计缺陷和问题仍未标记为已回答,我将发布我对解决此问题的看法 - 也许它会帮助任何人。这个解决方案实际上非常适用于NHibernate。
public class Parent
{
private readonly ISet<Child> _children = new HashedSet<Child> ();
public virtual IEnumerable<Child> Children { get { return new ImmutableSet<Child> (this._children); } }
protected internal virtual void AddChild (Child child)
{
this._children.Add(child);
}
}
public class Child
{
public virtual Parent Parent { get; protected set; }
protected Child()
{
}
public static Create (Parent parent)
{
if (parent == null)
throw new ArgumentNullException ("parent");
var child = new Child
{
Parent = parent
};
child.Parent.AddChild (child);
return child;
}
}
这与#2选项的不同之处在于,使用子对象本身而不是在#2中建议的父对象中收集子对象的创建(并使其初始值无效)。
如果我们使用个人工厂方法(Child.Create
)创建子对象,我不确定它是否被认为是不好的设计。
我希望有更多使用DDD经验的人可以对此发表评论。
答案 2 :(得分:0)
我倾向于使用选项(1) - 对我来说一直很好。重要的是不要将子集合本身暴露给外界 - 父母应该能够调解所有访问权限。但我很高兴在其他地方创建一个Child - 我只关心它被添加到Parent中,此时可以检查它的有效性等等。
我不明白你的规范示例:如果父母的孩子的任何的someCondition为true,那么你的ChildSpecification似乎会返回true。肯定 IsSatisfiedBy(Child child)只有在作为参数传递的特定子项满足条件时才返回true。