gpt4 book ai didi

Scala 蛋糕模式鼓励硬编码依赖关系?

转载 作者:行者123 更新时间:2023-12-03 04:27:55 25 4
gpt4 key购买 nike

我仍在尝试学习 Scala 的蛋糕模式。在我看来,它为您提供了集中“组件”配置的优势,以及为这些组件提供默认实现的能力(当然这是可重写的)。

然而,它使用 self 类型特征来描述依赖关系似乎混合了关注点。组件的目的(我认为)是抽象出该组件的不同实现。但是组件中描述的依赖项列表本身就是一个实现问题。

例如,假设我有一个充满小部件的数据库、一个允许我查找特定类型小部件的注册表,以及某种使用注册表来处理小部件的算法:

case class Widget(id: Int, name:String)

trait DatabaseComponent {
def database: (Int => Widget) = new DefaultDatabase()

class DefaultDatabase extends (Int => Widget) {
// silly impl
def apply(x: Int) = new Person(x, "Bob")
}
}

trait RegistryComponent {
this: DatabaseComponent => // registry depends on the database

def registry: (List[Int] => List[Widget]) = new DefaultRegistry()

class DefaultRegistry extends (List[Int] => List[Widget]) {
def apply(xs: List[Int]) = xs.map(database(_))
}
}

trait AlgorithmComponent {
this: RegistryComponent => // algorithm depends on the registry

def algorithm: (() => List[Widget]) = new DefaultAlgorithm()

class DefaultAlgorithm extends (() => List[Widget]) {
// look up employee id's somehow, then feed them
// to the registry for lookup
def apply: List[Widget] = registry(List(1,2,3))
}
}

现在您可以将它放在一些中央配置中:

object Main {
def main(args: Array[String]) {
val algorithm = new AlgorithmComponent() with RegistryComponent with DatabaseComponent

val widgets = println("results: " + algorithm.processor().mkString(", "))
}
}

如果我想更改为不同的数据库,我可以通过更改我的 mixin 轻松注入(inject)它:

val algorithm = new AlgorithmComponent() with RegistryComponent with SomeOtherDatabaseComponent


但是...如果我想混合使用不使用数据库的不同注册表组件怎么办?

如果我尝试使用不同的(非默认)实现对RegistryComponent进行子类化,RegistryComponent将坚持要求我包含DatabaseComponent依赖项。我必须使用RegistryComponent,因为这是顶级AlgorithmComponent 所需要的。

我错过了什么吗?当我在任何组件中使用自类型时,我就声明所有可能的实现都必须使用这些相同的依赖项。

还有其他人遇到过这个问题吗?类似蛋糕的解决方法是什么?

谢谢!

最佳答案

有了蛋糕图案,至少由example I always go to ,您应该将组件的接口(interface)定义与其默认实现分开。这将接口(interface)的依赖关系与实现的依赖关系清晰地分开。

trait RegistryComponent {
// no dependencies
def registry: (List[Int] => List[Widget])
}

trait DefaultRegistryComponent extends RegistryComponent {
this: DatabaseComponent => // default registry depends on the database

def registry: (List[Int] => List[Widget]) = new DefaultRegistry()

class DefaultRegistry extends (List[Int] => List[Widget]) {
def apply(xs: List[Int]) = xs.map(database(_))
}
}

关于Scala 蛋糕模式鼓励硬编码依赖关系?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9621183/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com