gpt4 book ai didi

scala - 为什么使用 scala 的蛋糕模式而不是抽象字段?

转载 作者:行者123 更新时间:2023-12-02 20:18:20 26 4
gpt4 key购买 nike

我一直在通过 cake pattern 阅读有关在 scala 中进行依赖注入(inject)的信息。我想我明白了,但我一定错过了一些东西,因为我仍然看不到其中的意义!为什么最好通过自身类型声明依赖项,而不仅仅是抽象字段?

给出 Programming Scala 中的示例TwitterClientComponent 使用蛋糕模式声明如下依赖项:

//other trait declarations elided for clarity
...

trait TwitterClientComponent {

self: TwitterClientUIComponent with
TwitterLocalCacheComponent with
TwitterServiceComponent =>

val client: TwitterClient

class TwitterClient(val user: TwitterUserProfile) extends Tweeter {
def tweet(msg: String) = {
val twt = new Tweet(user, msg, new Date)
if (service.sendTweet(twt)) {
localCache.saveTweet(twt)
ui.showTweet(twt)
}
}
}
}

这比如下将依赖项声明为抽象字段更好吗?

trait TwitterClient(val user: TwitterUserProfile) extends Tweeter {
//abstract fields instead of cake pattern self types
val service: TwitterService
val localCache: TwitterLocalCache
val ui: TwitterClientUI

def tweet(msg: String) = {
val twt = new Tweet(user, msg, new Date)
if (service.sendTweet(twt)) {
localCache.saveTweet(twt)
ui.showTweet(twt)
}
}
}

看看实例化时间,即 DI 实际发生的时间(据我所知),我很难看到 cake 的优点,特别是当您考虑到为 cake 声明需要进行额外的键盘输入时(包含特征) )

    //Please note, I have stripped out some implementation details from the 
//referenced example to clarify the injection of implemented dependencies

//Cake dependencies injected:
trait TextClient
extends TwitterClientComponent
with TwitterClientUIComponent
with TwitterLocalCacheComponent
with TwitterServiceComponent {


// Dependency from TwitterClientComponent:
val client = new TwitterClient

// Dependency from TwitterClientUIComponent:
val ui = new TwitterClientUI

// Dependency from TwitterLocalCacheComponent:
val localCache = new TwitterLocalCache

// Dependency from TwitterServiceComponent
val service = new TwitterService
}

现在再次使用抽象字段,或多或少相同!:

trait TextClient {
//first of all no need to mixin the components

// Dependency on TwitterClient:
val client = new TwitterClient

// Dependency on TwitterClientUI:
val ui = new TwitterClientUI

// Dependency on TwitterLocalCache:
val localCache = new TwitterLocalCache

// Dependency on TwitterService
val service = new TwitterService
}

我确信我一定错过了蛋糕的优越性!但是,目前我看不到它比以任何其他方式(构造函数、抽象字段)声明依赖项提供的功能。

最佳答案

具有自类型注释的特征比具有字段注入(inject)的老式 bean 更具可组合性,您可能在第二个片段中想到了这一点。

让我们看看如何实例化此特征:

val productionTwitter = new TwitterClientComponent with TwitterUI with FSTwitterCache with TwitterConnection

如果你需要测试这个特征,你可能会写:

val testTwitter = new TwitterClientComponent with TwitterUI with FSTwitterCache with MockConnection

嗯,有点违反 DRY 规定。让我们改进吧。

trait TwitterSetup extends TwitterClientComponent with TwitterUI with FSTwitterCache
val productionTwitter = new TwitterSetup with TwitterConnection
val testTwitter = new TwitterSetup with MockConnection

此外,如果组件中的服务之间存在依赖关系(例如 UI 依赖于 TwitterService),编译器将自动解决它们。

关于scala - 为什么使用 scala 的蛋糕模式而不是抽象字段?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7012013/

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