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