我仍然在嘗試學習Scala的蛋糕模式。在我看來,它爲您提供了集中配置「組件」的優勢,以及爲這些組件(當然可覆蓋)提供默認實現的能力。斯卡拉蛋糕模式鼓勵硬編碼的依賴關係?
但是,它使用自我類型特徵來描述依賴關係似乎混合了關注點。 Component(我認爲)的目的是抽象出該組件的不同實現。但是組件中描述的依賴列表本身是實現問題。
舉例來說,假設我有一個數據庫全小部件,註冊表,讓我去查詢特定類型的小部件,以及一些排序算法的使用註冊表來處理控件:
case class Widget(id: Int, name:String)
trait DatabaseComponent {
def database: (Int => Widget) = new DefaultDatabase()
class DefaultDatabase extends (Int => Widget) {
// silly impl
def apply(x: Int) = new Person(x, "Bob")
}
}
trait RegistryComponent {
this: DatabaseComponent => // registry depends on the database
def registry: (List[Int] => List[Widget]) = new DefaultRegistry()
class DefaultRegistry extends (List[Int] => List[Widget]) {
def apply(xs: List[Int]) = xs.map(database(_))
}
}
trait AlgorithmComponent {
this: RegistryComponent => // algorithm depends on the registry
def algorithm: (() => List[Widget]) = new DefaultAlgorithm()
class DefaultAlgorithm extends (() => List[Widget]) {
// look up employee id's somehow, then feed them
// to the registry for lookup
def apply: List[Widget] = registry(List(1,2,3))
}
}
現在你可以把它一起在一些中央配置:
object Main {
def main(args: Array[String]) {
val algorithm = new AlgorithmComponent() with RegistryComponent with DatabaseComponent
val widgets = println("results: " + algorithm.processor().mkString(", "))
}
}
如果我想換到不同的數據庫,我可以注入很容易通過改變我的mixin:
val algorithm = new AlgorithmComponent() with RegistryComponent with SomeOtherDatabaseComponent
但是...如果我想混合使用不同的註冊表組件,不使用數據庫?
如果我嘗試使用不同的(非默認)實現來繼承RegistryComponent,RegistryComponent將堅持包含一個DatabaseComponent依賴項。我必須使用RegistryComponent,因爲這是最高級的AlgorithmComponent所要求的。
我錯過了什麼嗎?在我的任何組件中使用自我類型的那一刻,我聲明所有可能的實現都必須使用這些相同的依賴關係。
有沒有其他人遇到過這個問題?什麼是解決它的蛋糕式的方式?
謝謝!
就像戴夫說的,你缺少接口,去耦合impls。如果你正在尋找缺少什麼蛋糕模式,那麼看看EJB和Spring:一個能夠意識到事務,安全和資源配置等問題的容器。蛋糕模式並沒有解決這個問題,因此,就像Google Guice一樣,它只是輕量級的。 – 2012-03-09 07:13:13