Domain driven design 用于创建骨料的工厂应放置在何处?

Domain driven design 用于创建骨料的工厂应放置在何处?,domain-driven-design,Domain Driven Design,我们可以将工厂放在聚合根上,放在与生成另一个对象密切相关的对象上,也可以将其实现为服务(通常创建整个聚合) a) 在大多数情况下,创建聚合根的工厂应该放在哪里(假设只创建根而不是整个聚合是合理的)?根本身 b) 同样,在大多数情况下,用于创建完整骨料的工厂应放置在何处 多谢各位 a) 在大多数情况下,创建聚合根的工厂应该放在哪里(假设只创建根而不是整个聚合是合理的)?根本身 当只创建聚合根对象本身有意义时,请提供工厂方法。在我看来,大多数时候,这只是一种静态的方便方法,用于分配内存和调用初始化例

我们可以将工厂放在聚合根上,放在与生成另一个对象密切相关的对象上,也可以将其实现为服务(通常创建整个聚合)

a) 在大多数情况下,创建聚合根的工厂应该放在哪里(假设只创建根而不是整个聚合是合理的)?根本身

b) 同样,在大多数情况下,用于创建完整骨料的工厂应放置在何处

多谢各位

a) 在大多数情况下,创建聚合根的工厂应该放在哪里(假设只创建根而不是整个聚合是合理的)?根本身

当只创建聚合根对象本身有意义时,请提供工厂方法。在我看来,大多数时候,这只是一种静态的方便方法,用于分配内存和调用初始化例程(
[Foo Foo WithBar:…]
,而不是Objective-C中的
[[Foo alloc]initWithBar:…]
),或者使用带有参数的构造函数(
例如Ruby中的新Foo(…)

b) 同样,在大多数情况下,用于创建完整骨料的工厂应放置在何处

测试是一个问题吗

我发现验证静态(工厂)方法行为是一个很难测试的问题。从本质上讲,您必须像对待遗留代码一样对待代码并进行重构,直到其可测试。但是,如果测试规定了代码,您就不会遇到这样的问题。与使用工厂方法模式不同,您将使用抽象工厂,并依赖其实例方法

因此,如果将工厂放在指定的工厂对象中:为了创建复杂的聚合对象,我倾向于使用多个工厂对象。那里有一个聚合根工厂,其他所有人都将与之交谈。它利用工厂制造骨料所用的组件。这样,您就不会将复杂的对象创建放在一个工厂中,而这个工厂随着代码库的发展会经常发生变化。相反,聚合根工厂依赖于其他工厂来初始化部件

工厂应该放在域层中,正如您的问题的评论者已经指出的那样


编辑:特别是当您使用多个工厂从存储库重新构建聚合时,这将非常有用。例如,如果放入深度嵌套的JSON,则只能测试工厂返回的对象。但是,如果您将创建子对象的任务委托给其他工厂,那么您将能够(1)在测试中模拟它们,(2)验证聚合根工厂(i)调用其协作者(ii)数据已被拆分。

我不知道这是否有帮助,但在Java中,我将它们放在同一个包(.net namespace)中作为它试图创建的类,作为工厂和服务(在我看来)是域模型的一部分。也许有些人更喜欢把工厂放在不同的包装中,但我认为这可能是风格的问题。我总是将这些工厂放在不同的类中,因为它们的职责与它们正在创建的对象的职责(构建对象与纯域逻辑)非常不同。是的,我知道工厂属于域层。我不认为有一套适用于所有情况的规则。它确实取决于你的领域和你想要达到的表现力类型。您可以在聚合本身上创建一个构造函数方法,让一个外部类为您构造聚合,或者让服务来完成这项工作。在某些情况下,您可能希望防范不变量,在其他情况下则不需要。重要的是,域表示业务意图。@user437291:如果聚合的创建逻辑相当复杂,则可以使用单独的类来完成此工作,但这些类实际上是域中的二等公民,除了创建对象之外没有其他功能。这可以应用于根实体和非根实体。但一般来说,在特定的聚合根上放置一个设计良好的工厂方法可以使您强制执行不变量和其他聚合的创建逻辑。还允许您使聚合更具表现力,因为其中包含创建逻辑。@user437291:我想说是的,在大多数情况下,让聚合负责自己的创建,并在更复杂的场景中或在有意义的地方使用工厂类。