2

我想實現的DDD所以我創建了以下類
- 用戶[域模型]
- UserRepository [中央工廠管理對象(S)]
- UserMapper + UserDbTable [映射器來映射應用程序功能並提供CRUD實現]領域驅動設計問題有關存儲庫

我的第一個問題是,當模型需要與持久層進行通信時,是否應該聯繫存儲庫或映射器?就我個人而言,我認爲它應該詢問將與映射器聯繫並提供所需功能的存儲庫。

現在我的第二個擔心是應該只有一個存儲庫用於同一類的所有對象,這意味着我將創建一個單例。但是如果我的應用程序有很多域模型(比如說20),那麼將會有20個單例。它感覺不對。另一種選擇是使用DI(依賴注入),但我使用的框架(Zend Framework 1.11)不支持DIC。

我的第三個

+0

您可以手動爲對象提供依賴關係。 DI容器是一種用於自動處理DI的工具。 – MikeSW 2012-04-22 07:29:43

回答

6
  • UserRepository [中央工廠管理對象(S)]

在DDD Repository是不是一個Factory。存儲庫負責域對象的中間和生命週期。工廠負責開始。從概念上說,堅持和恢復發生在中間生活中的域對象。

  • UserMapper + UserDbTable [A映射器來映射應用程序的功能,並提供CRUD執行]

這些類不屬於域層,這是數據訪問。它們都將被存儲庫實現封裝(如果使用ORM,則根本不存在)。

我的第一個問題是,當模型需要與 持久層進行通信時,是否應該聯繫存儲庫或映射器? 我個人認爲它應該詢問存儲庫,它將 聯繫映射器並提供所需的功能。

模型不需要與持久層進行通信。事實上,你應該儘可能讓你的模型儘可能地不依賴於持久性。從您的域模型的角度來看,Repository只是一個界面。這個接口的實現屬於不同的層 - 數據訪問。該實現稍後會注入到應用程序層的某處。應用程序層知道持久性和事務。這是您可以實施Unit Of Work模式(也不屬於域層)的位置。

現在我的第二個擔心是應該只有一個存儲庫用於同一類的所有對象,這意味着我將創建一個單例。但是如果我的應用程序有很多域模型(比如說20),那麼將會有20個單例。

首先,您可以有more than one給定域對象的存儲庫。無論如何,這是大多數情況下發生的事情,因爲您希望避免Repository接口上的「方法爆炸」。其次單身存儲庫是一個壞主意,因爲它會將所有消費者都耦合到一個單獨的實現中,除此之外,它會使單元測試變得困難。第三,擁有20個或更多的知識庫是沒有問題的,事實上你有更好的聚焦類,見SRP

UPDATE:

我想你混淆了正規廠家的模式和DDD廠。在DDD術語中,當從數據庫中恢復對象時,它在概念上已經存在(即使它是內存中的新對象)。因此,存儲庫的責任是堅持並恢復它。當複雜的域對象開始它的生命時,DDD Factory就會發揮作用 - 不管它是否是一個長壽命的對象(保存在數據庫中)。

+0

從技術上說,我正在使用Repository來執行「工廠」和「存儲庫」的功能。所以根據DDD我應該將功能分成多個類。 – Bryan 2012-04-22 04:21:06

+0

另外,如果我需要從持久層加載模型細節,哪個類負責 - UserFactory或UserRepository的實現?因爲根據DDD它的UserFactory任務創建具有所有依賴關係的新對象。我還分別實施了工作單元模式。 – Bryan 2012-04-22 04:31:17

+0

存儲庫是負責任的,因爲它知道如何從存儲恢復對象。如果使用RDBMS,則必須逐個重構對象,並且可以使用專用的Factory服務(作爲依賴項提供)。如果您使用的是文檔數據庫,那麼您並不需要它。基本上它取決於存儲庫的實施,但我認爲大多數時間回收可以在沒有外部幫助的情況下完成。 – MikeSW 2012-04-22 07:34:20

1

回答你的第二個問題。 ZF1的方式是爲每個對象類創建一個單例。你可以有一個工廠/註冊表爲你創建這些文件,並在你要求創建一個時返回以前創建的文件。或者,如果您使用PHP 5.3,請使用DI容器,如PimpleZend\Di

+0

足夠的了。我從我的答案中刪除了不正確的信息,以確保沒有人會感到困惑! – 2012-04-22 17:29:42