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

Bil*_*ill 73 scala

我刚看完并喜欢Cake模式文章.但是,在我看来,使用依赖注入的一个关键原因是您可以改变XML文件或命令行参数使用的组件.

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

Dav*_*ith 56

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

我们来看一个规范的蛋糕模式示例.您的模块被定义为traits,您的应用程序被构造为一个简单的Object,其中包含许多功能

val application =
    new Object
extends Communications
   with Parsing
   with Persistence
   with Logging
   with ProductionDataSource
application.startup
Run Code Online (Sandbox Code Playgroud)

现在所有这些模块都有很好的自我类型声明,这些声明定义了它们的模块间依赖关系,因此只有在所有模块间依赖关系存在,唯一且类型合适的情况下,该行才会编译.特别是,Persistence模块有一个self-type,它表示实现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
Run Code Online (Sandbox Code Playgroud)

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

  • @Dave:你真的建议你的"if"语句是生产就绪的,你可以部署到企业软件吗?这是恕我直言,实际上很差的代码,因为它无法将部署问题(哪个数据库)与代码问题(应用程序的组成方式)分开.查找数据库是应该在JNDI树中完成的; 它永远不应该硬编码,因为进行更改需要重新部署. (10认同)
  • 除非别无选择,否则我不会在生产代码中这样做.对于原始问题,这只是我所知道的最佳答案,这确实意味着需要在运行时更改应用程序的组成方式.简单地说"你永远不需要这样做,因为一切都可以通过单独配置组件"来解决问题. (6认同)
  • @jhclark生产,阶段,开发,测试:当您根据运行时条件处理多个数据库时,如何处理这些场景?上面的JNDI树参考是一个很好的参考,但是我不确定它是否涵盖了所有的基础,而蛋糕实现可以覆盖所有内容,只需要更多的样板,并且正如Dave在他的回答中提到的那样,"痛苦" ;-) (2认同)

she*_*lic 29

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

只需看看创业公司:

scala -cp first.jar:second.jar startupScript.scala
Run Code Online (Sandbox Code Playgroud)

没有什么不同于:

java -cp first.jar:second.jar com.example.MyMainClass context.xml
Run Code Online (Sandbox Code Playgroud)

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


Kev*_*ght 5

简短的回答是Scala目前没有任何动态mixin的内置支持.

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

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


sbl*_*ndy 0

Lift 内置了类似的东西。它主要是用 scala 代码编写的,但你有一些运行时控制。http://www.assembla.com/wiki/show/liftweb/Dependency_Injection