加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

斯卡拉蛋糕模式 – 我可以有多层蛋糕吗?

发布时间:2020-12-16 18:37:52 所属栏目:安全 来源:网络整理
导读:所以说我的应用程序中有两个依赖项,一些pub子系统的连接,以及与数据库的连接.我可以做点什么 trait DB { def lookup(query:String):String}trait PubSub { def subscribe(key:String,callback:String = Any)} 然后我就可以写出我的逻辑了 trait Functionalit
所以说我的应用程序中有两个依赖项,一些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的常用部分,但我们可以直接进行.)

此外,您没有混合原始方法名称;你必须编写代理或引用成员变量.

它错过了蛋糕模式的一些不错的方面,但根据我的经验,它最终比一大堆蛋糕层清晰得多.现在您可以看到您可以根据需要深入嵌套,并在需要的地方填写您想要的详细信息.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读