3

在我将应用程序从 2.4 迁移到 2.5(并摆脱所有静态引用)的过程中,我做了以下事情:

class Generic @Inject()(implicit val mat: Materializer, cache: CacheApi, wsClient: WSClient, configuration: play.api.Configuration) 
{ ... }

@Singleton
class Concrete1 @Inject() (gw:Generic) { ... }

@Singleton
class Concrete2 @Inject() (gw:Generic) { ... }

要使用它,我会使用 Generic 实例注入 Concrete1/2。它有效,但是在网上看到了其他几个关于它的例子之后,它似乎不太正确。

我正在考虑像这样修改它:

    abstract class Generic(cache: CacheApi, wsClient: WSClient, configuration: play.api.Configuration) 
    { ... }

    @Singleton
    class Concrete1(cache: CacheApi, wsClient: WSClient, configuration: play.api.Configuration) 
       extends Generic(cache, wsClient, configuration) { ... }

    @Singleton
    class Concrete2(cache: CacheApi, wsClient: WSClient, configuration: play.api.Configuration) 
       extends Generic(cache, wsClient, configuration) { ... }

然后为了能够做到:@Inject() (c1:Concrete1, c2:Concrete2) 我想我需要它们是由以下定义的模块:https ://www.playframework.com/documentation/2.5.x/ScalaDependencyInjection#Programmatic-bindings ?在这里做什么更有意义?

4

1 回答 1

1

我实际上不同意您的“似乎不太正确”的说法。

我认为您的第一个示例更接近地反映了组合优于继承的理念,这种理念已被接受为一种更易于维护的构建软件的方式。

在不了解您的ConcreteGeneric类的情况下,很难说更多,但如果后者基于继承的结构更容易正确地进行单元测试,我会感到非常惊讶,而模拟 a并将其注入测试类将是微不足道的.GenericConcrete

其他福利:

  • 减少噪音/重复声明
  • 与 Play 框架的联系较少(不需要模块定义)
  • 未来的灵活性(当你的具体类共享第二个“公共”类时)
于 2016-12-08T03:07:03.203 回答