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

Scala Cake Pattern:将大型组件拆分为单独的文件

发布时间:2020-12-16 18:48:14 所属栏目:安全 来源:网络整理
导读:我想使用Cake Pattern将某些软件系统的部分拆分成组件,使其完全模块化,如 this article所示.在最简单的情况下,我想要一些可模拟的组件,比如Logging,Config,Database,脚本等可能互相使用的脚本等.代码可能看起来像 trait AbstractConfig { def config: Abstra
我想使用Cake Pattern将某些软件系统的部分拆分成组件,使其完全模块化,如 this article所示.在最简单的情况下,我想要一些可模拟的组件,比如Logging,Config,Database,脚本等可能互相使用的脚本等.代码可能看起来像

trait AbstractConfig {
  def config: AbstractConfigInterface
  trait AbstractConfigInterface {
    def test: Unit
  }
}

trait SomeConfig extends AbstractConfig {
  this: Core =>  
  def config = SomeConfigImplementation
  object SomeConfigImplementation extends AbstractConfigInterface {
    def test = println("conf.test method called")
  }
}

trait AbstractDatabase {
  def database: AbstractDatabaseInterface
  trait AbstractDatabaseInterface {
    def connect: Unit
  }
}

trait SomeDatabase extends AbstractDatabase {
  this: Core =>
  def database = SomeDatabaseImplementation
  object SomeDatabaseImplementation extends AbstractDatabaseInterface {
    def connect = {
      println("connect method called")
      core.conf.test
    }
  }
}

trait Core {
  this: AbstractDatabase with AbstractConfig =>
  def core = CoreInterface
  object CoreInterface {
    def db = database
    def conf = config
  }
}

object app extends Core with SomeDatabase with SomeConfig

object Run {
  def main(args: Array[String]) = {
    app.core.db.connect
  }
}

这里的数据库和配置组件(SomeConfig和SomeDatabase特性)是可插拔的,如果需要可以更改为其他一些实现.他们的实现可以访问包含数据库和配置的核心对象,因此数据库可以在需要时访问配置,反之亦然.

所以问题是:如果像SomeDatabase这样的特性变得很大并且不适合单个文件,那么如何将它拆分成单独的类来保留对核心对象的访问?更具体地说,假设我需要将SomeDatabase中的连接方法中的一些代码移动到另一个文件中:

// SomeDatabase.scala
trait SomeDatabase extends AbstractDatabase {
  this: Core =>
  def database = SomeDatabaseImplementation
  object SomeDatabaseImplementation extends AbstractDatabaseInterface {
    def connect = {
      val obj = new SomeClass()
    }
  }
}

// SomeClass.scala in the same package
class SomeClass {
    core.conf.test // Does not compile - how to make it work??
}

SomeClass是SomeDatabase如何工作的实现细节,所以我显然不想把它作为特性并将其混合到应用程序中.有没有办法为SomeClass提供核心对象的访问权限?

一些相关链接:

> Dependency Injection vs Cake Pattern by Jan Machacek
> Real World Scala: Dependency Injection by Jonas Boner
> Dependency Injection in Scala: Extending the Cake Pattern by Adam Warsky
> Scalable Component Abstractions by Martin Odersky & Matthias Zenger

解决方法

最简单的方法是将Core in作为构造函数参数传递给SomeClass.

// SomeDatabase.scala
trait SomeDatabase extends AbstractDatabase {
  this: Core =>
  def database = SomeDatabaseImplementation
  object SomeDatabaseImplementation extends AbstractDatabaseInterface {
    def connect = {
      val obj = new SomeClass(SomeDatabase.this) // pass it here
    }
  }
}

// SomeClass.scala in the same package
class SomeClass(coreComp: Core) { // use it here
    coreComp.core.conf.test
}

有趣的是,我真的只想传递CoreInterface或AbstractConfigInterface,但事实上它们是内部类型确实很难.

(编辑:李大同)

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

    推荐文章
      热点阅读