首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >`trait`的依赖注入

`trait`的依赖注入
EN

Stack Overflow用户
提问于 2015-07-04 09:16:32
回答 1查看 4.1K关注 0票数 3

给定以下FooService

代码语言:javascript
复制
scala> trait FooService { 
     |   def go: Int 
     | }
defined trait FooService

还有一个MainService,它代表一个main方法。

代码语言:javascript
复制
scala> trait MainService extends FooService { 
     |   def f = go + 42
     | }
defined trait MainService

FooService可以有一个假的(用于测试)和一个真实的实现(例如命中DB ):

代码语言:javascript
复制
scala> object FakeService extends FooService { 
     |   def go = 10
     | }
defined object FakeService

scala> object RealService extends FooService {
     |   def go = 55 // in reality, let's say it hit the DB and got a value
     | }
defined object RealService

在我看来,添加一个"runner“类/特征,即运行sbt run将导致该类的执行,将是可行的。它看起来是这样的:

代码语言:javascript
复制
scala> class Main extends MainService {
     |   override def go = RealService.go
     | }
defined class Main

我也可以定义一个测试:

代码语言:javascript
复制
scala> class Test extends MainService {
     |   override def go = FakeService.go
     | }
defined class Test

我不确定这是否是定义真实MainService与测试a的惯用方式。请让我知道。

EN

回答 1

Stack Overflow用户

发布于 2015-07-04 22:59:28

您可以使用流行的蛋糕模式,这种模式也被称为"Scala方式“来进行依赖注入。

Jon对此做了一个很好的blog post演练(他还列出了一些替代方案)。

首先,FooService的特性

代码语言:javascript
复制
trait FooServiceComponent {
  val fooService: FooService

  trait FooService {
    def go: Int
  }
}

也就是说,我们需要两件事: 1.实际的对象,2.它的定义/实现。这两个名称空间都在一起。好的。以下是FakeReal版本:

代码语言:javascript
复制
trait FakeService extends FooServiceComponent {
  class FakeService extends FooService {
    def go = 10
  }
}

trait RealService extends FooServiceComponent {
  class RealService extends FooService {
    def go = 55
  }
}

现在,对于MainService

代码语言:javascript
复制
trait MainServiceComponent { this: FooServiceComponent =>
  val mainService: MainService

  class MainService extends FooService {
    def f = go + 42
    def go = fooService.go // using fooService
  }
}

请注意自输入this: FooServiceComponent,这是MainServiceComponent依赖于FooServiceComponent的一种Scala方式。如果您试图在不混入任何FooServiceComponent的情况下实例化MainServiceComponent,那么您将得到一个编译时错误。好的。:)

现在,让我们创建具有不同特征的TestMain对象:

代码语言:javascript
复制
object Test extends MainServiceComponent with FakeService {
  val mainService = new MainService()
  val fooService = new FakeService()
}

object Main extends MainServiceComponent with RealService {
  val mainService = new MainService()
  val fooService = new RealService()
}

请注意,由于名称空间的原因,不能在Main中访问FakeService,因为它没有混合在一起。好的。:)还要注意,直到此时才对类的任何实例化进行延迟,这很方便,因为您可以很容易地使用注册表或模拟库在一个地方替换它们。

结果:

代码语言:javascript
复制
println(Test.mainService.f) // -> 52
println(Main.mainService.f) // -> 97

我希望这能帮到你。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/31215914

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档