orr*_*lla 11 dependency-injection scala cake-pattern
我正在尝试使用Cake Pattern在Scala中实现依赖注入,但是遇到依赖冲突.由于我找不到具有此类依赖关系的详细示例,这是我的问题:
假设我们有以下特征(有2个实现):
trait HttpClient {
  def get(url: String)
}
class DefaultHttpClient1 extends HttpClient {
  def get(url: String) = ???
}
class DefaultHttpClient2 extends HttpClient {
  def get(url: String) = ???
}
以下两个蛋糕模式模块(在此示例中都是依赖于我们HttpClient的功能的API ):
trait FooApiModule {
  def httpClient: HttpClient        // dependency
  lazy val fooApi = new FooApi()    // providing the module's service
  class FooApi {
    def foo(url: String): String = {
      val res = httpClient.get(url)
      // ... something foo specific
      ???
    }
  }
}
和
trait BarApiModule {
  def httpClient: HttpClient        // dependency
  lazy val barApi = new BarApi()    // providing the module's service
  class BarApi {
    def bar(url: String): String = {
      val res = httpClient.get(url)
      // ... something bar specific
      ???
    }
  }
}
现在,在创建使用两个模块的最终应用程序时,我们需要为两个模块提供httpClient依赖关系.但是,如果我们想为每个模块提供不同的实现呢?或者只是简单地提供不同配置的不同实例(例如,使用不同ExecutionContext的实例)?
object MyApp extends FooApiModule with BarApiModule {
  // the same dependency supplied to both modules
  val httpClient = new DefaultHttpClient1()
  def run() = {
    val r1 = fooApi.foo("http://...")
    val r2 = barApi.bar("http://...")
    // ...
  }
}
我们可以在每个模块中以不同的方式命名依赖项,在它们前面加上模块名称,但这样做既麻烦又不优雅,如果我们自己没有对模块的完全控制也无法工作.
有任何想法吗?我是否误解了蛋糕模式?
你正确地得到了模式,你刚刚发现了它的重要限制.如果两个模块依赖于某个对象(例如HttpClient)并碰巧以相同的名称声明它(如httpClient),则游戏结束 - 您不会在一个Cake中单独配置它们.要么有两个蛋糕,就像丹尼尔建议或改变模块的来源,如果可以的话(正如Tomer Gabel暗示的那样).
每种解决方案都有其问题.
有两个蛋糕(丹尼尔的建议)看起来很好,他们不需要一些共同的依赖.
重命名一些依赖项(如果可能)会强制您调整使用这些依赖项的所有代码.
因此,有些人(包括我)喜欢对这些问题免疫的解决方案,例如使用普通的旧构造函数并完全避免使用Cake.如果你测量它,它们不会给代码增加太多膨胀(Cake已经非常冗长)并且它们更加灵活.
| 归档时间: | 
 | 
| 查看次数: | 517 次 | 
| 最近记录: |