Zend framework 关于存储库的域驱动设计问题

Zend framework 关于存储库的域驱动设计问题,zend-framework,dependency-injection,singleton,domain-driven-design,Zend Framework,Dependency Injection,Singleton,Domain Driven Design,我正在尝试实现DDD,因此我创建了以下类 -用户[域模型] -UserRepository[管理对象的中心工厂] -UserMapper+UserDbTable[映射应用程序功能并提供CRUD实现的映射器] 我的第一个问题是,当模型需要与持久层通信时,它应该联系存储库还是映射器?就我个人而言,我认为它应该询问存储库,该存储库将与映射器联系并提供所需的功能 现在我的第二个担忧是,对于同一类的所有对象,应该只有一个存储库,这意味着我将创建一个单例。但是如果我的应用程序有很多域模型(比如20个),那么

我正在尝试实现DDD,因此我创建了以下类
-用户[域模型]
-UserRepository[管理对象的中心工厂]
-UserMapper+UserDbTable[映射应用程序功能并提供CRUD实现的映射器]

我的第一个问题是,当模型需要与持久层通信时,它应该联系存储库还是映射器?就我个人而言,我认为它应该询问存储库,该存储库将与映射器联系并提供所需的功能

现在我的第二个担忧是,对于同一类的所有对象,应该只有一个存储库,这意味着我将创建一个单例。但是如果我的应用程序有很多域模型(比如20个),那么将有20个单例。而且感觉不对。另一种选择是使用DI(依赖注入),但我使用的框架(Zend framework 1.11)不支持DIC


我的第三个问题是回答你的第二个问题。ZF1的方法是为每个对象类创建一个单例。您可以有一个工厂/注册表为您创建这些,并在您请求已创建的工厂/注册表时返回先前创建的工厂/注册表。或者,如果您使用的是PHP5.3,请使用DI容器,如或

  • UserRepository[管理对象的中心工厂]
在DDD中,存储库不是一个。存储库负责域对象的生命周期的中期和末期。工厂负责开工。从概念上讲,持久化和恢复发生在域对象的中期

  • UserMapper+UserDbTable[映射应用程序功能并提供CRUD实现的映射器]
这些类不属于域层,这是数据访问。它们都将通过存储库实现进行封装(或者如果使用ORM,它们将根本不存在)

我的第一个问题是,当模型需要与 持久层应该联系存储库还是映射程序? 就我个人而言,我认为它应该询问存储库 联系映射器并提供所需的功能

模型不需要与持久层通信。事实上,您应该尽可能使您的模型具有持久性不可知性。从域模型的角度来看,存储库只是一个接口。该接口的实现属于不同的层-数据访问。稍后将在应用程序层的某个位置注入实现。应用层知道持久性和事务。这是您可以实现模式(也不属于域层)的地方

现在我的第二个担忧是,对于同一类的所有对象,应该只有一个存储库,这意味着我将创建一个单例。但是如果我的应用程序有很多域模型(比如20个),那么将有20个单例

首先,您可以拥有给定域对象的存储库。无论如何,大多数情况下都会发生这种情况,因为您希望避免存储库界面上的“方法爆炸”。其次,singleton Repository是个坏主意,因为它会将所有消费者耦合到一个实现中,这会使单元测试变得困难。第三,拥有20个或更多存储库没有什么错,事实上,您拥有的类越集中越好,请参见

更新:


我认为你们把常规的工厂模式和DDD工厂混淆了。在DDD术语中,当从数据库还原对象时,它在概念上已经存在(即使它是内存中的新对象)。因此,存储库有责任对其进行持久化和恢复。DDD Factory在复杂域对象开始使用时开始发挥作用-无论它是否是长寿命对象(保存在db中)。

从技术上讲,我现在使用存储库来执行“工厂”和“存储库”的功能。因此,根据DDD,我应该将功能分为多个类。另外,如果我需要从持久层加载模型细节,哪个类负责-UserFactory还是UserRepository的实现?因为根据DDD,它的UserFactory任务是创建具有所有依赖项的新对象。我还分别实现了工作单元模式。存储库负责,因为它知道如何从存储中恢复对象。如果使用RDBMS,则必须逐块重建对象,并且可以使用专用的Factory服务(作为依赖项提供)。如果您使用的是文档数据库,则不需要它。基本上,这取决于存储库的实现,但我认为大多数情况下,Repo可以在没有外部帮助的情况下实现它。@Dmitry AR本质上实现了UoW。不是以明确的方式,但功能是存在的。因此,由于模式UoW也属于域。@MikeSW:UoW不属于域层,因为它没有任何域含义,它的方法不基于泛在语言。UOW对您的领域专家来说没有意义,这是一个技术性问题,这就是为什么在DDD书中很少提到它(事实上我根本不记得有人提到过它)。您可以手动执行DI,为对象提供依赖关系。DI容器是一个用来自动处理DI的工具。我已经从我的答案中删除了错误的信息,以确保没有人被混淆!