简短版本
如果聚合不会凭空出现,并且这样做至少会导致业务建模中出现错误,为什么我们需要 DDD 中的工厂(注入(inject)应用程序层)?
长版
有一个流行的 DDD 示例,它是由以下聚合和实体组成的电子商务应用程序(过于简化)
建模为
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/