Scala Cake Pattern:将大型组件拆分为单独的文件
我想使用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 解决方法
最简单的方法是将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,但事实上它们是内部类型确实很难. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |