域对象、工厂和存储库之间的依赖关系
Dependencies between domain object, factory and repository
好的,我阅读了很多关于存储库模式的内容,包括 Fowler 的书。
我非常清楚它是什么以及它做了什么,但是我不太确定它是如何被工厂 and/or 域对象调用的。
我的理解是存储库应该像域对象的内存集合一样工作,而工厂是 class 负责实例创建的:new myDomainObject()
考虑到这一点,显然存储库需要引用工厂才能从数据源查询中创建新对象。
(存储库 -> 工厂)
域对象也需要引用工厂才能创建新对象。
我的困境是当域对象想要检索现有对象时,它应该调用存储库还是工厂?
如果它直接调用存储库(Domain -> Repository -> Factory),那么它需要同时拥有对工厂和存储库的引用,这对我来说似乎太多了,但有那么糟糕吗?
另一方面,如果它像 factory.CreateObjectWithId(id)
那样调用工厂,那么工厂只需要将调用重定向到存储库 repository.GetById(id)
,而这最后一个将调用另一个方法对象创建的同一工厂(如果它不在内存中)factory.CreateObject(dataset)
,因此导致循环引用:
Domain object -> Factory <--> Repository,这对我来说又不是什么好事。
那么您认为这些选项中哪个更好?或者还有其他选择吗?
您已经掌握了基础知识。 您的误解似乎来自于您假设领域对象应该是存储库的主要客户。事实并非如此,如果没有,您应该只从领域对象访问存储库另一种方式。一般尽量避免。
所以你的等式中缺少的部分是充当存储库的主要客户端的东西。
输入:应用程序服务
应用程序服务是包含用例逻辑(与域逻辑相反)的服务。它执行输入验证,实现访问管理,并负责事务控制。
这意味着应用服务将使用存储库从数据库加载聚合,对其进行处理,然后确保持久化更改(即提交事务)。
根据您使用的存储库的样式,将聚合保存回数据库会略有不同:
- 对于集合式存储库,应用服务通常使用工作单元来跟踪和提交更改。
- 使用命令式存储库,应用服务在对其执行业务操作后将聚合传递回存储库。
工厂和存储库
关于你关于工厂和存储库之间关系的问题,我想 也提供了你问题的答案。它的基本要点是:
- 使用存储库中的工厂来避免重复聚合的实例化逻辑。
- 确保概念从外部是清晰的,即不要将存储库看到的工厂的 "reconsitution interface" 暴露给其他 类。最好遵循 Interface Segregation Principle.
使用域中的存储库
如果您经常需要从数据库查询其他聚合以在域层执行业务任务,这表明您的聚合边界可能是错误的。
当然也有聚合边界没问题的情况,需要的对象不能作为参数传给领域对象。在这种情况下,使用域中的存储库是有意义的。在执行此操作之前,请务必尝试其他方法。在任何情况下,只依赖于存储库接口,从不依赖于具体的存储库实现。
好的,我阅读了很多关于存储库模式的内容,包括 Fowler 的书。 我非常清楚它是什么以及它做了什么,但是我不太确定它是如何被工厂 and/or 域对象调用的。
我的理解是存储库应该像域对象的内存集合一样工作,而工厂是 class 负责实例创建的:new myDomainObject()
考虑到这一点,显然存储库需要引用工厂才能从数据源查询中创建新对象。 (存储库 -> 工厂)
域对象也需要引用工厂才能创建新对象。
我的困境是当域对象想要检索现有对象时,它应该调用存储库还是工厂? 如果它直接调用存储库(Domain -> Repository -> Factory),那么它需要同时拥有对工厂和存储库的引用,这对我来说似乎太多了,但有那么糟糕吗?
另一方面,如果它像 factory.CreateObjectWithId(id)
那样调用工厂,那么工厂只需要将调用重定向到存储库 repository.GetById(id)
,而这最后一个将调用另一个方法对象创建的同一工厂(如果它不在内存中)factory.CreateObject(dataset)
,因此导致循环引用:
Domain object -> Factory <--> Repository,这对我来说又不是什么好事。
那么您认为这些选项中哪个更好?或者还有其他选择吗?
您已经掌握了基础知识。 您的误解似乎来自于您假设领域对象应该是存储库的主要客户。事实并非如此,如果没有,您应该只从领域对象访问存储库另一种方式。一般尽量避免。
所以你的等式中缺少的部分是充当存储库的主要客户端的东西。
输入:应用程序服务
应用程序服务是包含用例逻辑(与域逻辑相反)的服务。它执行输入验证,实现访问管理,并负责事务控制。
这意味着应用服务将使用存储库从数据库加载聚合,对其进行处理,然后确保持久化更改(即提交事务)。
根据您使用的存储库的样式,将聚合保存回数据库会略有不同:
- 对于集合式存储库,应用服务通常使用工作单元来跟踪和提交更改。
- 使用命令式存储库,应用服务在对其执行业务操作后将聚合传递回存储库。
工厂和存储库
关于你关于工厂和存储库之间关系的问题,我想
- 使用存储库中的工厂来避免重复聚合的实例化逻辑。
- 确保概念从外部是清晰的,即不要将存储库看到的工厂的 "reconsitution interface" 暴露给其他 类。最好遵循 Interface Segregation Principle.
使用域中的存储库
如果您经常需要从数据库查询其他聚合以在域层执行业务任务,这表明您的聚合边界可能是错误的。
当然也有聚合边界没问题的情况,需要的对象不能作为参数传给领域对象。在这种情况下,使用域中的存储库是有意义的。在执行此操作之前,请务必尝试其他方法。在任何情况下,只依赖于存储库接口,从不依赖于具体的存储库实现。