6

我已經討論了一段時間了,現在還沒有得出結論。 雖然我看到的大多數示例在應用程序層都有工廠代碼,但我傾向於認爲它應該位於領域層。 這樣做的原因: 我有時在我的工廠中完成了初始驗證,我希望所有對象都能通過創建。 我想要這個代碼在我的對象的所有實例上使用。 有時候一個操作需要傳遞給構造函數的參數信息,這些參數信息不自然。 還有一些不是重要的原因。工廠模式在DDD中應該在哪裏生活?

有沒有理由這是一個不好的做法? 這是否打破其他模式?

回答

4

+1這樣做。可訪問性是一個很好的理由,我會保持創建的代碼至少接近域模型層。否則,域模型的用戶將會很困惑如何在查找受限訪問構造函數時特別實例化它。實際上,將它分開的一個合理原因是你有不同的有效方法來創建相同的東西,例如在採用抽象工廠時通常就是這種情況。如果我不得不分開它,我會把它放在例如一個程序包(在Java的情況下)至少與領域模型的級別相同,並且總是隨同它一起運送它。

upper 
    --> domain 
    --> domain_factory 
+0

它會出現大多數人同意它在領域模型。那麼你在哪裏推薦你的工廠存在於域圖層中?一個單獨的程序集,文件夾,命名空間? – retslig

4

從記憶中,埃裏克埃文斯的書中有例子,對象工廠是領域層的很大一部分。

對我來說,在這裏找到你的工廠非常有意義。

7

DDD的工廠只是factory pattern的一個實例,因此應該在最有意義的地方使用它。另一個需要考慮的原則是information expert模式,它基本上規定應將行爲分配給最接近信息的類別。因此,如果您想要強制實施某些特定於域的規則和邏輯,請將工廠放在域圖層中 - 畢竟工廠會創建域對象。但請注意,您可能在其他圖層中有其他類型的工廠。

0

如果構建者/工廠只依賴於域類和基元,請將它們放在域圖層中,否則將它們放在域圖層之外。

0

我更喜歡應用層的工廠。

如果保持工廠領域層中,他們不會幫助你,當你需要的複雜類型作爲參數(C#代碼示例):

Application Layer: 

//this Factory resides in the Domain Layer and cannot reference anything else outside it 
Person person = PersonAggregateFactory.CreateDeepAndLargeAggregate(
      string name, string code, string streetName,... 
      and lots of other parameters...); 

//these ones reside in Application Layer, thus can be much more simple and readable: 
Person person = PersonAggregateFactory.CreateDeepAndLargeAggregate(CreatePersonCommand); 
Person person = PersonAggregateFactory.CreateDeepAndLargeAggregate(PersonDTO); 



Domain Layer: 

public class Person : Entity<Person> 
{ 
    public Address Address {get;private set;} 
    public Account Account {get;private set;} 
    public Contact Contact {get;private set;} 
    public string Name {get;private set;} 

    public Person(string name, Address address,Account account, Contact contact) 
    { 
     //some validations & assigning values... 
     this.Address = address; 
     //and so on... 

    } 

} 

public class Address:Entity<Address>{ 
    public string Code {get;private set;} 
    public string StreetName {get;private set;} 
    public int Number {get;private set;} 
    public string Complement {get;private set;} 
    public Address(string code, string streetName, int number, string complement?) 
    { 
     //some validations & assigning values... 
     code = code; 
    } 

} 

public class Account:Entity<Account>{ 
    public int Number {get;private set;} 

    public Account(int number) 
    { 
     //some validations & assigning values... 
     this.Number = number; 
    } 

} 

//yout get the idea: 
//public class Contact... 

此外,還有裏面的保持工廠沒有義務域層(從Domain Driven Design Quickly):

因此,把責任用於創建複雜 對象和聚集體的實例來單獨的對象,其本身可以具有 無重域名模式中的責任,但是仍然是 域名設計的一部分。提供一個接口,封裝所有複雜的程序集,並且不需要客戶端引用實例化對象的具體類。 創建整個 作爲一個單元聚合,執行它們的不變量。

由於我不使用工廠將持久對象加載到內存中,它們不必從除應用程序之外的其他層訪問。這也是爲什麼(從Domain Driven Design Quickly):

另一種看法是,工廠需要從頭開始創建新的對象 ,或者他們需要重建其 以前存在的對象,但一直很可能持續到 數據庫。 從實體 中將實體帶回到內存中涉及完全不同於 創建新實體的過程。一個明顯的區別是新的對象不需要新的身份。該對象已經有一個。 違反不變量的處理方式不同。 當從頭開始創建新對象 時,任何違反不變量的事件都會以異常結束 。我們不能用 數據庫重新創建對象。對象需要以某種方式修復,因此他們 可以正常工作,否則會有數據丟失。