[英]Domain Driven Design - Parent child relation pattern - Specification pattern
I was wondering which of the following is considered to be a best practice when dealing with parent child relationships. 我想知道在处理父母子女关系时,以下哪项被认为是最佳做法。
1) The following example seems to be a common practice, but when creating an instance of a child, it will be in an invalid state as long as it is not added to the parent. 1)以下示例似乎是一种常见做法,但在创建子实例时,只要未添加到父级,它就处于无效状态。 Couldn't this lead to problems regarding validation etc.
这不会导致验证等问题。
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) The next sample would take care that a child must always be related to its parent. 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) In the last example that child takes care of the relation to its parent itself. 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;
}
}
Which pattern is considered the best? 哪种模式被认为是最好的? I believe that pattern 2 might be the best since then a child can never exist without a relation to its parent.
我相信模式2可能是最好的,因为如果没有与父母的关系,孩子就永远不会存在。 This would make it easier eg when implementing a specification pattern that might do things like:
这将使得例如在实现可能执行以下操作的规范模式时更容易:
public class ChildSpecification
{
bool IsSatisfiedBy(Child child)
{
return child.Parent.Children.Where(someCondition).Count > 0;
}
}
The above specification can only work if a child has a parent. 上述规范只有在孩子有父母的情况下才有效。
What do you think? 你怎么看? Do you know better ways?
你知道更好的方法吗? Thanks in advance
提前致谢
I definitely like suggestion number 2, but I think that it misses something important that is found in 3, namely that if a Child
object cannot exist without a Parent
it should take a Parent
object in its constructor. 我非常喜欢建议2,但我认为它错过了3中发现的重要内容,即如果没有
Parent
就不能存在Child
对象,那么它应该在其构造函数中使用Parent
对象。 Furthermore the Parent
property on the Child
class should be read only. 此外,
Child
类的Parent
属性应该是只读的。 So you would end up with something like: 所以你最终会得到类似的东西:
public class Parent
{
private ICollection<Child> children;
public ReadOnlyCollection Children { get; }
public Child CreateChild()
{
var child = new Child(this);
children.Add(child);
return child;
}
}
public class Child
{
internal Parent Parent
{
get;
private set;
}
internal Child(Parent parent)
{
this.Parent = parent;
}
}
Since I've just encountered the same design desissions and question still not marked as answered I'll post my vision on solution of this problem - maybe it'll help anyone. 由于我刚刚遇到了相同的设计缺陷和问题仍未标记为已回答,我将发布我对解决此问题的看法 - 也许它会帮助任何人。 This solution actually perfectly viable for use with NHibernate.
这个解决方案实际上非常适合与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;
}
}
That's differs from your #2 option in a way that creation of the child object (and invalidating it's initial values) are gathered withing child object itself and not in parent object as you suggested in #2. 这与您的#2选项的不同之处在于,创建子对象(并使其初始值无效)是使用子对象本身而不是在#2中建议的父对象中收集的。
Tho one thing I'm not sure if it's considered bad design or not if we create child objects with personal factory method ( Child.Create
). 如果我们用个人工厂方法(
Child.Create
)创建子对象,那么我不确定它是否被认为是糟糕的设计。
I hope someone with more experience in using DDD could comment on that. 我希望有更多使用DDD经验的人可以对此发表评论。
I tend to use option (1) - has always worked well for me. 我倾向于使用选项(1) - 对我来说一直很好。 The important thing is not to expose the children collection itself to the outside world - the Parent should be able to mediate all the access.
重要的是不要将子集合本身暴露给外界 - 父母应该能够调解所有访问权限。 But I'm perfectly happy for a Child to be created elsewhere - I only care about it when it gets added to the Parent, and at this point it can be checked for validity etc. etc.
但我很高兴在其他地方创建一个孩子 - 我只关心它,当它被添加到父母,并在这一点上,它可以检查有效性等。
I don't understand your specification example: it seems like your ChildSpecification would return true if any of the parent's children has someCondition as true. 我不明白你的规范示例:如果父母的任何一个孩子的someCondition为true,看起来你的ChildSpecification会返回true。 Surely IsSatisfiedBy(Child child) should only return true if the specific child passed as a parameter satisfied the condition.
肯定IsSatisfiedBy(Child child)只有在特定子项作为参数满足条件时才返回true。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.