如何在没有硬编码的情况下使用Cake模式进行依赖注入?

时间:2011-03-02 19:12:56

标签: scala

我只是阅读并享受the Cake pattern article。但是,在我看来,使用依赖注入的一个关键原因是您可以改变XML文件或命令行参数所使用的组件。

如何使用Cake模式处理DI的这个方面?我看到的例子都涉及静态混合特征。

5 个答案:

答案 0 :(得分:56)

由于在Scala中静态混合特征,如果要改变混合到对象中的特征,请根据某些条件创建不同的对象。

让我们来看一个典型的蛋糕模式示例。您的模块被定义为traits,您的应用程序被构造为一个简单的Object,其中包含许多混合在一起的功能

val application =
    new Object
extends Communications
   with Parsing
   with Persistence
   with Logging
   with ProductionDataSource
application.startup

现在所有这些模块都有很好的自我类型声明来定义它们的模块间依赖关系,因此只有在所有模块间依赖关系存在,唯一且类型合适的情况下,该行才会编译。特别是,Persistence模块有一个自我类型,它表示任何实现Persistence的东西都必须实现DataSource,一个抽象模块特征。由于ProductionDataSource继承自DataSource,所以一切都很棒,而且应用程序构造线也会编译。

但是如果你想使用不同的DataSource,指向一些本地数据库进行测试呢?进一步假设您不能仅使用从某些属性文件加载的不同配置参数重用ProductionDataSource。在这种情况下你要做的是定义一个新的特性TestDataSource,它扩展了DataSource,并将其混合在一起。您甚至可以根据命令行标志动态执行此操作。

val application = if (test)
  new Object
    extends Communications
      with Parsing
      with Persistence
      with Logging
      with TestDataSource
else
  new Object
    extends Communications
      with Parsing
      with Persistence
      with Logging
      with ProductionDataSource

application.startup

现在看起来比我们想要的更冗长,特别是如果你的应用程序需要改变它在多个轴上的构造。从好的方面来说,通常你只有一个条件构造逻辑块在应用程序中(或者最坏的情况是每个可识别的组件生命周期),所以至少可以最大限度地减少痛苦,并将其与逻辑的其余部分隔离开来。

答案 1 :(得分:29)

Scala也是一种脚本语言。因此,您的配置XML可以是Scala脚本。它是类型安全的,而不是一种不同的语言。

简单地看一下创业公司:

scala -cp first.jar:second.jar startupScript.scala

并没有那么不同:

java -cp first.jar:second.jar com.example.MyMainClass context.xml

您可以随时使用DI,但还有一个工具。

答案 2 :(得分:5)

简短的回答是,Scala目前还没有动态mixin的内置支持。

我正在研究autoproxy-plugin以支持这一点,虽然它目前处于暂停状态,直到2.9发布,当时编译器将具有新功能,使其变得更容易。

与此同时,实现几乎完全相同功能的最佳方法是将动态添加的行为实现为包装类,然后将隐式转换添加回包装成员。

答案 3 :(得分:3)

在AutoProxy插件可用之前,实现效果的一种方法是使用委托:

trait Module {
  def foo: Int
}

trait DelegatedModule extends Module {
  var delegate: Module = _
  def foo = delegate.foo
}

class Impl extends Module {
  def foo = 1
}

// later
val composed: Module with ... with ... = new DelegatedModule with ... with ...
composed.delegate = choose() // choose is linear in the number of `Module` implementations

但请注意,这样做的缺点是它更冗长,如果在特征中使用var s,则必须小心初始化顺序。另一个缺点是,如果上面Module内存在路径相关类型,您将无法轻松使用委托。

但是如果有大量不同的实现可以改变,那么与列出具有所有可能组合的案例相比,可能会花费更少的代码。

答案 4 :(得分:0)

Lift内置了这些内容。它主要是在scala代码中,但你有一些运行时控制。 http://www.assembla.com/wiki/show/liftweb/Dependency_Injection