2012-03-27 97 views
1

我有一個聚合,包括實體AAbstractElement,X,YZ。根實體是A,它也有一個AbstractElement的列表。實體X,YZ繼承自AbstractElement。我需要將X,YZ的實例添加到A的實例的可能性。一種方法是對每種類型使用一種方法,即addX,addYaddZ。這些方法將以創建實例X,YZ所需的值爲參數。但是,每當我添加一個繼承自AbstractElement的新類型時,我需要修改實體A,所以我認爲這不是最好的解決方案。創建子實體的聚合根和實例

另一種方法是使用抽象添加方法addAbstractElement來添加AbstractElement實例。但是,在這種情況下,該方法將採用AbstractElement的實例作爲參數。由於這種方法將被位於聚集之外的實體調用,因此遵循DDD規則/建議,這些外部實體是否有權創建AbstractElement的實例?我在埃裏克埃文斯的書中讀到,外部實體無權持有除根之外的聚合實體的引用?

這種問題的最佳做法是什麼?

感謝

回答

5

埃文的書,第139頁:

含義:「如果你需要添加一個已經存在的骨料中的元素,你可能對總的根目錄中創建一個工廠方法」 ,您應該在根(A)上創建一個工廠方法,以獲取AbstractElement的詳細信息。該方法將根據某個決策參數創建AbstractElement(X/Y/Z),並將其添加到AbstractElements的內部集合中。最後,這個方法返回新元素的id。

最好的問候,

Itzik Saban

+0

就我而言,細節從一個實體到另一個實體是不同的。要創建X的實例,我需要一個字符串。要創建一個Y的實例,我需要兩個字符串......在這種情況下它是如何工作的?我怎樣才能只使用一種方法? – 2012-03-27 14:28:24

+0

您不受DDD限制只能創建一種方法 - 只要它們充當工廠方法,就可以創建3種不同的方法。 – ItzikSaban 2012-03-27 14:36:15

+0

但是在這種情況下,我在問題中提出的問題依然存在。每次添加新類型時,我都需要添加一個新的工廠方法。 – 2012-03-27 15:48:55

2

幾點意見。正如前面的回答者所說,使用工廠方法是一種很好的做法。如果你能避免它,那麼絕對不要創建對象。通常情況下,這是一個非常大的氣味,並且錯過了讓您的域名更有意義的機會。

我寫了一個小例子來說明這一點。視頻在這種情況下是聚合根。聚合界限內是視頻對象及其相關注釋。評論可以是匿名的,也可以是已知的用戶編寫的(爲了簡化示例,我用一個用戶名錶示了用戶,但很明顯,在真實應用程序中,您將擁有類似UserId的內容)。

下面是代碼:

public class Video { 
    private List<Comment> comments; 

    void addComment(final Comment.Builder builder) { 
     this.comments.add(builder.forVideo(this).build()); 
     // ... 
    } 
} 


abstract public class Comment { 
    private String username; 
    private Video video; 

    public static public class Builder { 
     pubic Builder anonymous() { 
      this.username = null; 
      return this; 
     } 

     pubic Builder fromUser(final String username) { 
      this.username = username; 
      return this; 
     } 

     pubic Builder withMessage(final String message) { 
      this.message = message; 
      return this; 
     } 

     public Builder forVideo(final Video video) { 
      this.video = video; 
      return this; 
     } 

     pubic Comment build() { 
      if (username == null) { 
       return new AnonymousComment(message); 
      } else { 
       return new UserComment(username, message); 
      } 
     } 
    } 
} 

public class AnonymousComment extends Comment { 
    // ... 
} 

static public class UserComment extends Comment { 
    // ...  
} 

一件事也思考上是聚合邊界包含對象,而不是類。因此,很可能某些類(主要是價值對象,但它也可能是實體的情況)在許多集合中被表示。