我想知道在
Scala中使用函数和DI模式的区别.我想出了以下理解,我想知道这种理解是否正确.
让我们想象一个依赖图.
1)如果我们使用函数作为构建块,那么图形由作为边的函数和作为边的参数组成.
2)如果我们使用traits作为构建块(如Cake中),那么图形由作为节点的特征和作为边缘的抽象成员组成.
那么Cake模式的目的是什么?为什么2优于1?这是课程粒度.通过将函数分组为特征可以简化图形1,然后我们可以使用更小,更易理解的图形-2.相关概念的分组/聚类是一种压缩形式,可以创造理解(我们需要掌握更少的东西才能获得理解).
这是一个不同的比较(Cake与包系统之间):
Cake类似于将相关函数分组到包中,但它超出了这个范围,因为使用名称空间(包/对象)会导致依赖关系变得难以连接,Cake正在用自身类型注释/抽象成员替换具有特征和导入的包/对象.包和Cake模式之间的区别在于,依赖项的实际实现可以使用Cake进行更改,而使用包时却无法更改.
我不知道这些类比是否有意义,如果不是,请纠正我,如果是,请向我保证.我仍然试图围绕Cake模式,以及如何将它与我已经理解的概念(函数,包)联系起来.
最佳答案 依赖注入(DI)通常用getter / setter(我假设你的意思是函数)和/或构造函数params来完成. 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方法.无法保证依赖性被注入.如果您使用某些DI框架,您可以强制注入某些内容,但是您的DI不再与您的框架无关.现在,如果使用构造函数方法,则每当我们实例化时(无论框架如何)都必须提供依赖关系:
class NeedsALogger(logger: Logger) {
// uses a Logger here
}
现在,蛋糕图案如何适应?首先,让我们的示例适应Cake Pattern:
class NeedsALogger {
logger: Logger =>
// Uses a Logger here
}
我们来谈谈记录器:Logger =>.这是一种自我类型,它只是将Logger的成员带入范围而无需扩展Logger. NeedsALogger不是Logger,因此我们不想扩展它.但是,NeedsALogger需要一个Logger,这就是我们用自我类型完成的.我们要求在创建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!
正如您所看到的,我们使用任何一种方法都可以完成同样的事情对于很多DI,构造函数方法就足够了,所以你可以根据自己的偏好选择.我个人喜欢自我类型和蛋糕模式,但我看到很多人也避免它.
要继续阅读有关蛋糕模式的信息,请查看this.如果您想了解更多信息,这是一个很好的下一步.