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

时间:2017-07-21 03:01:35

标签: design-patterns domain-driven-design

我使用工厂按命令对象创建实体,但是当我想从命令对象更新实体时,我找不到一个好的模式来执行此操作。我应该只使用工厂来更新实体,或者如果没有,那么什么是好的模式?

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);
     }
}

4 个答案:

答案 0 :(得分:4)

在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 +事件源,您可以通过提取从存储库中识别并加载聚合的通用Application layer来消除command handler,它会向命令发送命令,它收集事件,然后将它们保存到Event store。我经常使用这种风格。

答案 1 :(得分:3)

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

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

我的建议:与我已经提到的“服务”主题保持一致:例如,引入 UpdateService 类是否合理?当然,如果有用于更新和创建的通用代码,那么这应该再次被考虑到公共类中。

答案 2 :(得分:1)

在Domain Driven Design中,应用程序通常直接与聚合根进行交互。

 public Product updateProduct(long productId, ProductCommand command) {
     Product product = productRepository.findOne(productId);

     product.update(productCommand);

     return productRepository.save(product);
 }

答案 3 :(得分:1)

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

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

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

1)调用存储库以通过id检索要更新的实体。

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

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