- UserRepository [管理对象的中央工厂]
在 DDD 存储库中不是工厂。存储库负责域对象的中间和结束生命周期。工厂负责开始。从概念上讲,持久化和恢复发生在域对象的中年。
- UserMapper + UserDbTable [映射应用程序功能并提供 CRUD 实现的映射器]
这些类不属于域层,这是数据访问。它们都将被存储库实现封装(或者如果您使用 ORM,则根本不存在)。
我的第一个问题是,当模型需要与持久层通信时,它应该联系存储库还是映射器?我个人认为它应该询问将联系映射器并提供所需功能的存储库。
模型不需要与持久层通信。实际上,您应该尝试使您的模型尽可能与持久性无关。从您的领域模型的角度来看,Repository 只是一个接口。这个接口的实现属于不同的层——数据访问。稍后在您的应用程序层中的某个位置注入该实现。应用层知道持久性和事务。这是您可以实现工作单元模式(也不属于域层)的地方。
现在我关心的第二个问题是同一个类的所有对象应该只有一个存储库,这意味着我将创建一个单例。但是如果我的应用程序有很多领域模型(比如说 20 个),那么就会有 20 个单例。
首先,对于给定的域对象,您可以拥有多个存储库。无论如何,这在大多数情况下都会发生,因为您想避免存储库界面上的“方法爆炸”。其次,单例存储库是一个坏主意,因为它将所有消费者耦合到一个实现中,除其他外,这会使单元测试变得困难。第三,拥有 20 个或更多存储库并没有错,事实上,你拥有的课程越集中越好,请参阅SRP。
更新:
我认为您混淆了常规工厂模式和 DDD 工厂。在 DDD 术语中,当对象从数据库中恢复时,它在概念上已经存在(即使它是内存中的新对象)。因此,存储库的责任是持久化和恢复它。当复杂的域对象开始生命时,DDD 工厂开始发挥作用——无论它是否是一个长期存在的对象(保存在数据库中)。