Noe*_*edy 25 dependency-injection scala cake-pattern
我一直在阅读通过蛋糕模式在scala中执行依赖注入.我想我明白了,但我一定错过了一些东西,因为我仍然看不到它的重点!为什么通过自我类型而不仅仅是抽象字段来声明依赖性更好?
鉴于编程中 的示例,ScalaTwitterClientComponent使用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)
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
这比将依赖关系声明为抽象字段更好吗?
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)
}
}
}
Run Code Online (Sandbox Code Playgroud)
看看实例化时间,也就是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
}
Run Code Online (Sandbox Code Playgroud)
现在再次使用抽象字段,或多或少相同!:
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
}
Run Code Online (Sandbox Code Playgroud)
我敢肯定我一定不能错过蛋糕的优越感!但是,目前我无法看到它以任何其他方式声明依赖关系(构造函数,抽象字段).
具有自我类型注释的特征比具有场注入的老式豆类更具组合性,您可能在第二个片段中考虑过这些特征.
让我们来看看你将如何实现这个特性:
val productionTwitter = new TwitterClientComponent with TwitterUI with FSTwitterCache with TwitterConnection
Run Code Online (Sandbox Code Playgroud)
如果您需要测试这个特性,您可能会写:
val testTwitter = new TwitterClientComponent with TwitterUI with FSTwitterCache with MockConnection
Run Code Online (Sandbox Code Playgroud)
嗯,有点DRY违规.让我们改进吧.
trait TwitterSetup extends TwitterClientComponent with TwitterUI with FSTwitterCache
val productionTwitter = new TwitterSetup with TwitterConnection
val testTwitter = new TwitterSetup with MockConnection
Run Code Online (Sandbox Code Playgroud)
此外,如果组件中的服务之间存在依赖关系(比如UI依赖于TwitterService),它们将由编译器自动解析.
想想如果TwitterService使用会发生什么TwitterLocalCache.如果TwitterService自我输入会更容易,TwitterLocalCache因为TwitterService无法访问val localCache你声明的内容.Cake模式(和自我键入)允许我们以更加通用和灵活的方式注入(当然,除此之外).
| 归档时间: |
|
| 查看次数: |
3071 次 |
| 最近记录: |