我应该使用工厂来更新对象吗?



我使用工厂通过命令对象创建实体,但是当我想从命令对象更新实体时,我找不到一个好的模式来做到这一点。我应该只使用工厂来更新实体,或者如果没有,什么是好的模式?

interface ProductFactory {
Product create(ProductCommand command);
Product update(Product product, ProductCommand command);
}

我的服务:

class ProductServiceImpl {
public Product updateProduct(long productId, ProductCommand command) {
Product product = productRepository.findOne(productId);
product = productFactory.update(product, productCommand);
return productRepository.save(product);
}
}

在 DDD 上,其中一个战略因素是在代码中使用无处不在的语言。因此,在您的特定情况下,类方法应根据它们的作用命名,例如Product::changeTitlePriduct::changePrice

此外,还有多种建筑风格。其中一个没有命令对象,但具有多个参数,如下所示:

class ProductService {
public void changeProductPrice(long productId, double newPrice) {
Product product = productRepository.findOne(productId);
product.changePrice(product, newPrice);
productRepository.save(product);
}
}

这种风格遵循了很多无处不在的语言。

另一种样式是带有命令对象参数的:

class ProductCommandHandler {
public void handleChangeProductPrice(ChangeProductPrice command) {
Product product = productRepository.findOne(command.getAggregateId ());
product.handleChangeProductPrice(command);
productRepository.save(product);
}
}

第二种样式非常适合 CQRS+Event 溯源,您可以通过提取从存储库中标识和加载聚合的通用command handler来消除Application layer,它向其发送命令,收集事件,然后将它们保存到Event store。我经常使用这种风格。

仅命名就可以回答您的问题。工厂负责创造东西。是的,在现实世界中,有时工厂会收回他们创造的东西来更新它们(想想这里的德国汽车制造商(。

但在软件方面,将工厂变成"维护站"似乎是不好的做法。例如,它与单一责任原则相冲突。除此之外,更新对象的工厂非常罕见,因此让源代码的人类读者感到惊讶。而且您希望避免阅读您的代码的人感到惊讶

我的建议:与我已经提到的"服务"主题保持一致:例如,引入UpdateService类是否有意义?当然,当有用于更新和创建的公共代码时,应该再次将其分解到一个公共类中。

在域驱动设计中,应用程序通常直接与聚合根交互。

public Product updateProduct(long productId, ProductCommand command) {
Product product = productRepository.findOne(productId);
product.update(productCommand);
return productRepository.save(product);
}

工厂用于创建对象,而不是用于更新对象。

更新实体是一个持久性方面,由存储库完成。

您必须在应用程序层执行以下操作:

1( 调用存储库以按 id 检索要更新的实体。

2( 使用从命令中获取的值修改所需的实体属性。这是通过调用更新属性的实体方法完成的。你不应该在工厂里这样做。工厂仅用于创建实体。修改实体是实体提供的一种行为(方法(。

3( 调用存储库以保留实体。

最新更新