我想知道在Scala中使用functions和Cake模式进行DI的区别。我提出了以下理解,我想知道这个理解是否正确。
让我们想象一个依赖图。
1)如果我们使用函数作为构建块,那么图由函数作为节点和参数作为边组成。
2)如果我们使用特征作为构建块(就像在Cake中一样),那么图由特征作为节点,抽象成员作为边组成。
那么蛋糕模式的目的是什么呢?为什么2比1好?它是过程粒化。Graph-1可以通过将函数分组为特征来简化,然后我们就有了一个更小、更容易理解的Graph-2。相关概念的分组/聚类是压缩的一种形式,并创建理解(我们需要在头脑中持有较少的东西来获得理解)。
这是一个不同的比较(在Cake和package系统之间):
Cake类似于将相关函数分组到包中,但它超越了这一点,因为使用名称空间(包/对象)会导致依赖关系被硬连接,Cake用特征替换包/对象,用自身类型注释/抽象成员替换import。packages和Cake模式之间的不同之处在于,依赖项的实际实现可以使用Cake更改,而在使用packages时不能更改。
我不知道这些类比是否有意义,如果没有,请纠正我,如果是,请向我保证。我仍然在试图理解Cake模式,以及如何将它与我已经理解的概念(函数、包)联系起来。
发布于 2017-11-07 05:25:10
依赖注入(DI)通常是通过getters/setter(我假设你指的是函数)和/或构造函数参数来完成的。getter/setter方法可能如下所示:
trait Logger {
// fancy logging stuff
}
class NeedsALogger {
private var l: Logger = _
def logger: Logger = l
def logger_=(newLogger: Logger) {
l = newLogger
}
// uses a Logger here
}我真的不喜欢getter/setter方法。不能保证依赖项会被注入。如果你使用某些依赖注入框架,你可以强制注入一些东西,但是你的依赖注入对你的框架不再是不可知的。现在,如果您使用构造函数方法,则必须在每次实例化时提供依赖项(与框架无关):
class NeedsALogger(logger: Logger) {
// uses a Logger here
}现在,Cake模式是如何适应的呢?首先,让我们将我们的示例应用于Cake模式:
class NeedsALogger {
logger: Logger =>
// Uses a Logger here
}让我们来谈谈logger: Logger =>吧。这是一个自类型,它只是将Logger的成员带入作用域,而不必扩展Logger。NeedsALogger不是Logger,所以我们不想扩展它。但是,NeedsALogger需要一个Logger,这就是我们使用self类型实现的。我们要求在创建NeedsALogger时必须提供Logger。用法如下所示:
trait FooLogger extends Logger {
// full implementation of Logger
}
trait BarLogger extends Logger {
// full implementation of Logger
}
val a = new NeedsALogger with FooLogger
val b = new NeedsALogger with BarLogger
val c = new NeedsALogger // compile-time error! 正如您所看到的,我们使用这两种方法都可以完成相同的事情。对于很多依赖注入来说,构造函数方法就足够了,所以你可以根据自己的喜好来选择。我个人喜欢self-types和Cake模式,但我看到很多人也避免使用它。
要继续阅读关于蛋糕模式的具体内容,请查看this。如果你想了解更多,这是一个很好的下一步。
https://stackoverflow.com/questions/41359085
复制相似问题