2010-01-28 70 views
6

我想知道在處理父子關係時,以下哪一項被認爲是最佳實踐?域驅動設計 - 父子關係模式 - 規範模式

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

我傾向於使用選項(1) - 一直對我很好。重要的是不要將孩子們收集到外部世界 - 家長應該能夠調解所有的訪問。但是我很高興在別處創建了一個孩子 - 我只在將它添加到父母時關心它,並且此時可以檢查其是否有效等。

我不明白你的規範示例:如果父項的子項的任何的someCondition爲true,則您的ChildSpecification將返回true。當然IsSatisfiedBy(兒童孩子)只應該返回true,如果特定的孩子作爲參數傳遞滿足條件。

+0

規範模式是關於我目前在我的一個項目中遇到的特殊情況。一個孩子有一個有效日期範圍,它不應該與子集合中任何其他孩子的任何其他有效日期範圍相交。你會認爲這是父母的規範嗎? – Chris 2010-01-28 16:25:09

+0

我可能會在Parent的addChild()方法中實現這個作爲警戒條件。家長然後不允許添加例如拋出異常。在這種情況下,我可能不會使用規範。 – alasdairg 2010-01-28 17:07:02

+0

但我需要在UI上檢查。所以當拋出異常時,我不得不接受這一點。這也不是很優雅。而afaik關於規範的好處是我可以在很多不同的場景中使用它,例如1.)在我的域oe中2.)在客戶端應用程序中預先驗證業務邏輯。或者我錯了? – Chris 2010-01-28 17:20:10

5

我絕對喜歡建議2號,但我認爲它忽略了在3發現,即如果沒有Parent不能存在Child對象應採取在其構造Parent對象重要的東西。此外,屬性Child類應該只讀。 所以,你最終會得到這樣的:

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; 
    } 
} 
+0

我會這樣做,如果規範是一個孩子應該總是有一個父,並且不知道它的父母是不能創建的。 所以,只是2和3的組合。 +1 – 2010-01-28 17:05:28

1

因爲我剛剛遇到了同樣的設計desissions和問題,爲回答我會後對這個問題的解決方案我的視力仍然沒有標明 - 也許它會幫助任何人。這個解決方案實際上非常適合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選項不同的方式,子對象(和無效它的初始值)的創建聚集withing子對象本身,而不是在父對象,你在#2建議。

如果我們用個人工廠方法創建子對象(Child.Create),我不確定它是否被認爲是不好的設計。

我希望有更多使用DDD經驗的人可以對此發表評論。