斯卡拉蛋糕模式 – 我可以有多层蛋糕吗?
所以说我的应用程序中有两个依赖项,一些pub子系统的连接,以及与数据库的连接.我可以做点什么
trait DB { def lookup(query:String):String } trait PubSub { def subscribe(key:String,callback:String => Any) } 然后我就可以写出我的逻辑了 trait Functionality { this:DB with PubSub => def doSomething() { val key = lookup("get key") subscribe(key,data => println(data)) } } 然后我的应用程序可以像 object Awesome extends App { object repository extends Functionality with DB with PubSub { def lookup(query:String) = "some key" def subscribe(key:String,callback:String => Any) { scala.concurrent.ops.spawn { while(true) { callback(key) ; Thread.Sleep(1000) } } } } repository.doSomething() } 这一切在世界上都很好. 但是,如果我想要连接两个在同一个应用程序中共享相同数据库实现的pub子系统呢? 我想做点什么 object Awesome2 extends App { object repository extends DB { def lookup(query: String): String = "some other key" object connection1 extends Functionality with PubSub with DB { def subscribe(key: String,callback: (String) => Any) { scala.concurrent.ops.spawn { while(true) { callback(key.toUpperCase) ; Thread.sleep(1000) } } } } object connection2 extends Functionality with PubSub with DB { def subscribe(key: String,callback: (String) => Any) { scala.concurrent.ops.spawn { while(true) { callback(key.toLowerCase) ; Thread.sleep(1000) } } } } } } 第二层蛋糕中的对象(隐式地?)在父级别的DB实现中啜饮. 但scala编译器告诉我 error: object creation impossible,since method lookup in trait DB of type (query:String) String is not defined object connection2 extends Functionality with PubSub with DB { 如果我做了以下,那么它会做我想要的 object Awesome3 extends App { object repository extends DB { override def lookup(query: String): String = "some other key" object connection1 extends Functionality with PubSub with DB { def subscribe(key: String,callback: (String) => Any) { scala.concurrent.ops.spawn { while(true) { callback(key.toUpperCase) ; Thread.sleep(1000) } } } def lookup(query: String): String = repository.lookup(query) } object connection2 extends Functionality with PubSub with DB { def subscribe(key: String,callback: (String) => Any) { scala.concurrent.ops.spawn { while(true) { callback(key.toLowerCase) ; Thread.sleep(1000) } } } def lookup(query: String): String = repository.lookup(query) } } repository.connection1.doSomething() repository.connection2.doSomething() } 但这有点乱 我可以添加这个特性 trait DB_Base extends DB { private val db:DB = this trait DB_Layer extends DB { def lookup(query:String):String = db.lookup(query) } } 然后是以下工作 object Awesome4 extends App { object repository extends DB_Base { override def lookup(query: String): String = "some other key" object connection1 extends Functionality with PubSub with DB_Layer { def subscribe(key: String,callback: (String) => Any) { scala.concurrent.ops.spawn { while(true) { callback(key.toUpperCase) ; Thread.sleep(1000) } } } } object connection2 extends Functionality with PubSub with DB_Layer { def subscribe(key: String,callback: (String) => Any) { scala.concurrent.ops.spawn { while(true) { callback(key.toLowerCase) ; Thread.sleep(1000) } } } } } repository.connection1.doSomething() repository.connection2.doSomething() } 所以现在我有两层.我怎么得到三个?我觉得我正在失去情节. 解决方法
评论不足以解释它,所以这里有一个基本上说“不要那样做!”的答案.并建议一个替代方案.
您遇到的关键问题是您希望拥有某些功能的多个副本,但您无法通过名称(仅按类型)引用它.解决方案是:给它起个名字. 让我们采取你的双蛋糕模式. trait Foo { def foo(s: String): String } trait Bar { def bar(s: String,f: String => Any): Any } trait Bippy { this: Foo with Bar => def bip(s: String) = bar(foo(s),println) } 好吧,太棒了,我们可以将Bippy与任何实现Foo和Bar的东西混合在一起,我们就可以进行双击.但是,如果Foo和Bar在不同级别实施呢?如果我们改为 trait Bippy { def myFoo: Foo def myBar: Bar def bip(s: String) = myBar.bar(myFoo.foo(s),println) } 这最初看起来更尴尬. (确实如此.)但它现在让你混合搭配,而不是被迫以越来越尴尬的方式结块.例如: object Foozle extends Foo { theFoo => def foo(s: String) = s.toUpperCase trait BippyImpl extends Bippy { this: Bar => def myFoo = theFoo def myBar = this } object Woozle1 extends BippyImpl with Bar { def bar(s: String,f: String => Any) = f(s) } object Woozle2 extends BippyImpl with Bar { def bar(s: String,f: String => Any) = f(s.reverse) } } 现在,您可以随处混合和匹配任何功能;唯一的缺点是你必须命名它. (这里我们创建了一个嵌套特性BippyImpl,以便分割出Woozles的常用部分,但我们可以直接进行.) 此外,您没有混合原始方法名称;你必须编写代理或引用成员变量. 它错过了蛋糕模式的一些不错的方面,但根据我的经验,它最终比一大堆蛋糕层清晰得多.现在您可以看到您可以根据需要深入嵌套,并在需要的地方填写您想要的详细信息. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |