我想使用蛋糕模式将某些软件系统的各个部分拆分为组件,以使其完全模块化,如 this article 中提出的那样。 。在最简单的情况下,我想要一些可模拟的组件,比如说日志记录、配置、数据库、脚本等,它们可能会相互使用。代码可能看起来像
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
特征)是可插入的,并且可以根据需要更改为其他一些实现。他们的实现可以访问包含数据库和配置的core
对象,因此数据库可以在需要时访问配置,反之亦然。
所以问题是:如果像 SomeDatabase
这样的特征变得很大并且不适合单个文件,如何将其拆分为单独的类来保留对 core
的访问权限> 对象?更具体地说,假设我需要将 SomeDatabase
中的 connect 方法中的一些代码移至另一个文件:
// 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
提供对 core
对象的访问?
一些相关链接:
最佳答案
最简单的做法是将 Core
作为构造函数参数传递给 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
,但它们是内部类型这一事实确实让这变得很困难。
关于Scala 蛋糕图案 : Splitting large components into separate files,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10251892/