Domain driven design DDD中工厂的一些令人困惑的事情

Domain driven design DDD中工厂的一些令人困惑的事情,domain-driven-design,Domain Driven Design,a) 我有点困惑,在大多数情况下,我们应该只拥有一个工厂来生产整个聚合,还是应该拥有一个工厂来只创建聚合根 b) 构建整个聚合的工厂应该自己构建根对象和非根对象,还是应该将非根实体/VO的构建委托给其他工厂 因此,如果Aggregate包含5种不同类型的非根实体,那么Aggregate factory应该自己创建这些非根实体,还是应该有另外5个工厂(每个非根实体一个工厂),哪个Aggregate factory将委托创建特定类型的非根实体 谢谢你埃里克·埃文斯的DDD书,第138页,用粗体写着:

a) 我有点困惑,在大多数情况下,我们应该只拥有一个工厂来生产整个聚合,还是应该拥有一个工厂来只创建聚合根

b) 构建整个聚合的工厂应该自己构建根对象和非根对象,还是应该将非根实体/VO的构建委托给其他工厂

因此,如果Aggregate包含5种不同类型的非根实体,那么Aggregate factory应该自己创建这些非根实体,还是应该有另外5个工厂(每个非根实体一个工厂),哪个Aggregate factory将委托创建特定类型的非根实体


谢谢你

埃里克·埃文斯的DDD书,第138页,用粗体写着:

将整个聚合创建为一个整体,强制执行它们的不变量。

然后在下一页:

工厂只能以一致的方式生产对象 国家。对于实体,这意味着创建整个聚合 [……]


具体地说,这意味着您只有一个工厂来创建整个聚合。构建非根实体或值对象可能涉及其他类(工厂),但只有一个工厂负责创建聚合。此工厂创建完整的聚合,而不仅仅是根对象。

子根对象(例如,
订单的
OrderItem
)的创建由根实体本身处理,因此它可以以外部世界看不见的方式强制执行变体

因此,典型的流量可能是:

var newOrder = orderFactory.CreateOrder(customer);

newOrder.AddOrderItem(product, quantity);

工厂可以在实体内使用,但外部世界不应访问工厂

public class Order
{
     private OrderItemFactory _orderItemFactory;

     public AddOrderItem(Product product, int Quantity)
     {
          var newOrderItem = _orderItemFactory.CreateOrderItem(product, quantity);
     }
}`

为什么不让工厂专用于特定类型(以及聚合工厂将委托创建特定类型),特别是考虑到我们可能经常希望在预先存在的聚合中添加元素,在这种情况下,我们必须为创建非根对象创建工厂?@user437291:我想您可以为非根对象创建工厂,但根对象的工厂仍应创建完整有效的聚合。有一个只创建根的工厂是没有意义的,但它可能会在其他类/工厂的帮助下创建非根对象。但我假设您也要指出的是,创建一个完整的聚合的工作被划分到几个工厂中(而不是由一个工厂创建所有的对象)没有带来任何好处?@user437291:如果您需要像您提到的那样“将元素添加到预先存在的聚合中”,并且构建这些元素是复杂的,那么我想为这个对象创建一个工厂可能会带来一些好处。但是默认情况下,我会为每个聚合使用一个工厂。请问这是否意味着
非root
可以有它们的工厂方法,并且在创建整个聚合的过程中由
AR
使用?如果答案是肯定的,那么如何防止客户机代码或其他聚合误用非root`factory方法!“工厂可以在实体内使用,但外部世界不应该访问它。”因此,在任何情况下,都不应该将非根工厂实现为服务?工厂不是服务,而是工厂。服务处理实体之间的交互(包括与外部世界的交互),而工厂抽象出实例化。您可能会发现需要在根之外创建非根对象—在这种情况下,您需要查看您的模型。要么子对象不在根目录中,要么你应该遍历根目录。“工厂不是服务,它是工厂。”但根据Evans的说法,如果需要,工厂也可以作为服务实现——在这种情况下,工厂是服务?!你指的是埃文斯书的哪一部分?工厂是一个对象,它封装了对象实例化,并允许替换其他实现。虽然服务可能会实例化对象,但它应该在内部适当地将其推迟到工厂,以避免违反单一责任原则。我可以问一下
OrderItem
是否有自己的工厂方法并在根工厂方法中使用吗?在这种情况下,我们如何防止客户端代码在非根聚合中误用工厂方法?