gpt4 book ai didi

Scala 蛋糕模式和依赖冲突

转载 作者:行者123 更新时间:2023-12-04 01:59:28 26 4
gpt4 key购买 nike

我正在尝试使用 Cake Pattern 在 Scala 中实现依赖注入(inject),但遇到了依赖冲突。由于我找不到具有此类依赖关系的详细示例,因此这是我的问题:

假设我们有以下特征(有 2 个实现):

trait HttpClient {
def get(url: String)
}

class DefaultHttpClient1 extends HttpClient {
def get(url: String) = ???
}

class DefaultHttpClient2 extends HttpClient {
def get(url: String) = ???
}

以及以下两个蛋糕模式模块(在本例中,它们都是依赖于我们的 HttpClient 功能的 API):

trait FooApiModule {
def httpClient: HttpClient // dependency
lazy val fooApi = new FooApi() // providing the module's service

class FooApi {
def foo(url: String): String = {
val res = httpClient.get(url)
// ... something foo specific
???
}
}
}



trait BarApiModule {
def httpClient: HttpClient // dependency
lazy val barApi = new BarApi() // providing the module's service

class BarApi {
def bar(url: String): String = {
val res = httpClient.get(url)
// ... something bar specific
???
}
}
}

现在,在创建使用这两个模块的最终应用程序时,我们需要提供 httpClient两个模块的依赖关系。但是如果我们想为每个模块提供不同的实现呢?或者只是提供不同配置的依赖关系实例(例如,使用不同的 ExecutionContext)?

object MyApp extends FooApiModule with BarApiModule {
// the same dependency supplied to both modules
val httpClient = new DefaultHttpClient1()

def run() = {
val r1 = fooApi.foo("http://...")
val r2 = barApi.bar("http://...")
// ...
}
}

我们可以在每个模块中以不同的方式命名依赖项,并在它们前面加上模块名称,但这会很麻烦且不优雅,而且如果我们自己不能完全控制模块,也将无法工作。

有任何想法吗?我误解了蛋糕图案吗?

最佳答案

您正确地获得了模式,并且您刚刚发现了它的重要限制。如果两个模块依赖于某个对象(比如 HttpClient)并且碰巧以相同的名称声明它(比如 httpClient),那么游戏就结束了——你不会在一个 Cake 中单独配置它们。要么有两个蛋糕,就像丹尼尔建议的那样,或者如果可以的话,改变模块的来源(正如 Tomer Gabel 暗示的那样)。

这些解决方案中的每一个都有其问题。

拥有两个 Cakes(Daniel 的建议)看起来不错,只要它们不需要一些常见的依赖项。

重命名某些依赖项(如果可能的话)会强制您调整所有使用这些依赖项的代码。

因此,有些人(包括我)更喜欢不受这些问题影响的解决方案,比如使用普通的旧构造函数并完全避免使用 Cake。如果你测量它,它们不会给代码增加太多的臃肿(Cake 已经很冗长)而且它们更加灵活。

关于Scala 蛋糕模式和依赖冲突,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20459882/

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