java - DDD - 为什么我们需要工厂?

标签 java oop architecture domain-driven-design factory

简短版本

如果聚合不会凭空出现,并且这样做至少会导致业务建模中出现错误,为什么我们需要 DDD 中的工厂(注入(inject)应用程序层)?

长版

有一个流行的 DDD 示例,它是由以下聚合和实体组成的电子商务应用程序(过于简化)

enter image description here

建模为

class Customer {
  private CustomerId id;
  // related business rules and processes
}

class Order{
  private OrderId id;
  private List<OrderLine> orderLines;
  // related business rules and processes
}

class OrderLine{
  private OrderLineId id;
  private int quantity;
  private ProductId product;
  // related business rules and processes
}
class Product{} 
// etc...

众所周知,订单的创建是通过工厂完成的,通常如下所示:

Order order = orderFactory.createNewOrder(customer);

但是我认为这个模型不是很清楚,因为我假设原始(虚构的)要求是

Customers can place orders.

那么,将订单的创建委托(delegate)给 Customer 聚合并使代码更加冗长不是更有意义吗?即:

Order order = customer.placeOrder(...);
// Pass the data needed for the creation of the object, or even the factory service if the creation is complex

在我看来,扩展这个 View 将导致系统的参与者在大多数情况下都是聚合的,并且它们将包含用例的所有调用(其侧面 -效果是应用层也很薄)

第二种方法是否违反了 DDD ?负责创建另一个聚合的聚合感觉不太好,但会生成更好的代码,在我看来,这些代码可以更好地匹配域。

最佳答案

Does this second approach violate DDD

没有。埃文斯在领域驱动设计一书中描述的模式应该被理解为“重复出现的有用想法”,而不是“这些模式是强制性的”。

您会在文献中找到对以下观点的支持:当我们对聚合的创建进行建模时,我们应该使用领域语言,而不是工厂。例如:Don't Create Aggregate Roots (乌迪·达汉,2009)。

也就是说......当 Evans 在他的书中描述 FACTORY 模式时,他是在生命周期管理而不是建模的背景下这样做的。换句话说,工厂是存储库和聚合的表兄弟,而不是域实体和值对象。

Shift the responsibility for creating instances of complex objects and AGGREGATES to a separate object, which may itself have no responsibility in the domain model but is still a part of the domain design.

换句话说,我们可能仍然希望在域模型中使用 Customer::placeOrder,但让该方法将对象组​​装委托(delegate)给专用工厂。


当然,对象创建并不是我们使用工厂模式的唯一地方;它也可以出现在对象重构中。常见的 REPOSITORY 模式是从持久数据存储中获取信息,然后将该信息传递给 FACTORY,以将该信息排列成适当的形状 - 也就是构成 AGGREGATE 的对象图。


我理解工厂模式以information hiding为例,当我们决定改变一组固定信息组装成聚合体的方式时,工厂限制了爆炸半径。

关于java - DDD - 为什么我们需要工厂?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67030874/

相关文章:

java - 手动将 FieldError 添加到 bindingResult 时,Spring 表单输入值丢失

javascript - 当需要一个类并调用另一个方法中的方法时,到底发生了什么?

Java继承附加一个函数而不是覆盖它

c# - 通过依赖注入(inject)传递计时器并配置/启动计时器

android - 我可以识别应用程序分发吗?

java - 如何使用可选项实现这个嵌套流程?

使用 Apache commons 的 Java FTP 抛出 "IOException caught while copying"

java - 数据类型为 Double 且值为 '0.0' 的变量未出现在 JSON 响应中

oop - 为不同的(曲线制作)类编写一个可移植(寻根器)解算器类

architecture - 如何在 DDD 中设计多阶段任务