使用构建器模式时防止静态注入

Preventing static injection when using builder pattern

简介

我将 Dagger 2 用于一个使用 DDD 原则建模的项目。

我想使用 Builder Pattern 来创建复杂的实体,我通常获取构建器实例的方式是使用静态工厂方法:ComplexEntity.builder().

聚合根将获得强类型 ID,即 ComplexEntityID,这需要新实例的值生成器。现在我的模块中有一个方法:@Provides ComplexEntityID provideComplexEntityID(IdValueGenerator generator) { return new ComplexEntityID(generator.nextId(); }.

ComplexEntityBuilder 需要 ComplexEntityID 的实例(或提供者)才能创建 ComplexEntity。但是出于充分的理由,来自 Guice 和 Dagger(以及其他)的人建议不要使用静态注入。

问题

如何在不使用静态注入的情况下使用构建器创建 ComplexEntity 的实例?换句话说,如何获取构建器的实例?

坚持 ComplexEntity.builder() 会很好,因为这是一个常见的约定,但我认为在不使用 new () 关键字的情况下使实例在静态方法中可用的唯一方法是使用静态注入。

我能想到的另一种方法是也创建 ComplexEntityFactory 并将 builder() 方法放在那里。但是把factory和builder一起使用好像有点奇怪:

  1. 在class你需要的地方注入一个工厂
  2. complexEntityFactory.builder().value1(...) .value2(...) .build();

在这种情况下,推荐的方法是什么?

编辑:如果它毕竟是一个专门的工厂,那么如果这个工厂仍然可以使用AutoFactory或类似的东西生成,那就太好了

我认为有比评论中jaco0646提出的更优雅的解决方案:

构建器是一种特殊的服务:您使用它们来实现特定目标,但它们在域内没有生命周期或意义。

所以就像注入任何其他服务一样注入构建器。

这有几个优点:

  • 构建者可以依赖其他服务和工厂来使用它们。在您的情况下,这是对 ComplexEntityID.
  • 工厂的依赖
  • 对构建器的依赖是明确的(这是一件好事)。目前,您的依赖项隐藏在对静态方法的调用中。
  • 您可以在测试中替换生成器。

总的来说,这种方法提高了内聚性并减少了耦合。

需要注意的一个潜在陷阱是构建器通常具有内部状态(与典型服务不同)。因此,请确保配置您的依赖项注入容器,以便为每个解析请求创建一个新的构建器实例。