私はケーキパターンを介してscalaで依存性注入を行うことについて読んでいます。私はそれを理解していると思いますが、まだ要点が見えないので、何かを見逃しているに違いありません! 単なる抽象フィールドではなく、自己型を介して依存関係を宣言する方が望ましいのはなぜですか?
Programming Scala の例ではTwitterClientComponent
、cake パターンを使用して次のように依存関係を宣言しています。
//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が実際に発生するインスタンス化時間を見ると(私が理解しているように)、ケーキの利点を理解するのに苦労しています。特に、ケーキ宣言(囲み特性)のために必要な追加のキーボード入力を考慮すると
//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
}
私はケーキの優位性について何かを見逃しているに違いない! ただし、現時点では、他の方法 (コンストラクター、抽象フィールド) で依存関係を宣言することで何が提供されるのかわかりません。