Я все еще пытаюсь выучить Шаблон Торта Скалы.Мне кажется, что это дает вам преимущество централизации вашей конфигурации «Компонентов», а также возможность предоставлять реализации по умолчанию для этих компонентов (которые, конечно, могут быть переопределены).
Однако, это использование selfчерты типа для описания зависимостей, кажется, смешивают проблемные области.Цель Компонента (я думаю) состоит в том, чтобы абстрагироваться от различных реализаций этого компонента.Но список зависимостей, описанный в Компоненте , сам по себе является проблемой реализации .
Например, допустим, у меня есть база данных, полная виджетов, реестр, который позволяет мне искать определенные видывиджетов и какой-то алгоритм, который использует реестр для обработки виджетов:
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(", "))
}
}
Если я хочучтобы перейти на другую базу данных, я могу легко добавить ее, изменив свой миксин:
val algorithm = new AlgorithmComponent() with RegistryComponent with SomeOtherDatabaseComponent
Но ... что если я захочу смешать другой компонент реестра, который не использует базу данных ?
Если я попытаюсь создать подкласс RegistryComponent с другой реализацией (не по умолчанию), RegistryComponent будет настаивать на том, чтобы я включил зависимость DatabaseComponent.И я должен использовать RegistryComponent, потому что это то, что требует AlgorithmComponent верхнего уровня.
Я что-то упустил?В тот момент, когда я использую собственный тип в любом из моих Компонентов, я заявляю, что все возможные реализации должны использовать те же самые зависимости.
Кто-нибудь еще сталкивался с этой проблемой?Как Cake-like способ ее решения?
Спасибо!