2012-04-20 76 views
6

我想使用一些軟件系統的分割部分的蛋糕圖案成組件,使其完全模塊化爲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 
    } 
} 

這裏的數據庫,並配置組件(SomeConfigSomeDatabase特點)都是可插拔的,在需要時可以改變一些其他實現。它們的實現可以訪問保存數據庫和配置的對象core,因此數據庫可以根據需要訪問配置,反之亦然。

所以現在的問題是:如果真像SomeDatabase一些特質變大,不適合到一個單一的文件如何將其拆分成獨立的類固定接入core對象?更具體地講,比方說我需要在SomeDatabase移動一些代碼OUT連接方法的另一個文件:

// 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對象?


一些相關鏈接:

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

回答

2

做的是最簡單的事情將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 
} 

有趣的是,我真的只是想通過CoreInterfaceAbstractConfigInterface,但事實證明,他們是內部類型確實做出困難。

+0

戴夫,感謝您的回答。到目前爲止,這似乎是唯一合理的方法。唯一不關心的是在任何核心方法的每次調用中輸入'coreComp.'的必要性。不幸的是,似乎沒有直接使用'CoreInterface'的選項,是嗎? – nab 2012-04-23 08:06:59

+1

您可以'輸入coreComp._'來減少輸入。 – leedm777 2012-04-23 14:25:45