Meine Frage ist sehr ähnlich zu Scala Cake Pattern and Dependency Collisions. Aber ich bemühe mich, eine konkrete Lösung zu finden, wie sie in Daniel Cs Antwort vorgeschlagen wird.Scala Cake Pattern: Wie Dependency Collisions vermeiden?
So, hier ist das Problem:
A ProductDetailsPage
(Zug) erfordert zwei unabhängige Servicemodule ProductServiceModule
und SessionModule
, implementiert durch ProductServiceModuleWs
und SessionModuleWs
sind.
Beide Module basieren auf einem RestServiceConfigurationProvider
.
Für diese RestServiceConfigurationProvider
ist nur eine konkrete Implementierung verfügbar: DefaultRestServiceConfigurationProvider
(atm).
Die DefaultRestServiceConfigurationProvider
auf der anderen Seite hängt von der RestEndpointProvider
, die entweder ein HybrisEndpointProvider
oder sein kann ProductServiceEndpointProvider
Kurz, ProductServiceModuleWs
und SessionModuleWs
verbinden Dienste Remote-REST-konformen Web. Die genaue IP-Adresse des bestimmten Dienstes wird von einer Implementierung des RestEndpointProvider bereitgestellt.
Nun, das ist, wo die Kollisionen passiert. Probieren Sie den folgenden Code aus. Der störende Ort, an dem die Abhängigkeitskollision stattfindet, ist durch einen Kommentar markiert.
Zu Recht rügt der Compiler über die beiden widerstreitenden Implementierungen der RestEndpointProvider
, nämlich HybrisEndpointProvider
und ProductServiceEndpointProvider
Als Daniel in seiner Antwort erwähnt, keine solche Kollisionen zu vermeiden, habe ich separat die ProductServiceModuleWs
und SessionModuleWs
verdrahten sollte, jede mit ihrer eigenen konkreten RestEndpointProvider Implementierung, vielleicht wie so
new ProductServiceModuleWs
with DefaultRestServiceConfigurationProvider
with ProductServiceEndpointProvider
new SessionModuleWs
with DefaultRestServiceConfigurationProvider
with HybrisEndpointProvider
Aber hier ist, wo ich stecken geblieben.
Wie können diese zwei separat konfigurierten Module jetzt in die ProductDetailsPage
injiziert werden, wobei Abhängigkeitskollisionen vermieden werden, aber trotzdem das Kuchenmuster verwendet wird?
Hier ist der Beispielcode. Der Code ist eigenständig und sollte in Ihrer IDE ausgeführt werden.
case class RestEndpoint(url: String, username: Option[String] = None, password: Option[String] = None)
trait RestEndpointKey {
def configurationKey: String
}
case object HybrisEndpointKey extends RestEndpointKey { val configurationKey = "rest.endpoint.hybris" }
case object ProductServiceEndpointKey extends RestEndpointKey { val configurationKey = "rest.endpoint.productservice" }
trait ProductDetailsPage {
self: ProductServiceModule with SessionModule =>
}
trait ProductServiceModule {}
trait SessionModule {}
trait ProductServiceModuleWs extends ProductServiceModule {
self: RestServiceConfigurationProvider =>
}
trait SessionModuleWs extends SessionModule {
self: RestServiceConfigurationProvider =>
}
trait RestServiceConfigurationProvider {}
trait DefaultRestServiceConfigurationProvider extends RestServiceConfigurationProvider {
self: RestEndpointProvider =>
}
sealed trait RestEndpointProvider {
def endpointKey: RestEndpointKey
}
trait HybrisEndpointProvider extends RestEndpointProvider {
val endpointKey = HybrisEndpointKey
}
trait ProductServiceEndpointProvider extends RestEndpointProvider {
val endpointKey = ProductServiceEndpointKey
}
object Example extends App {
new ProductDetailsPage
with ProductServiceModuleWs
with SessionModuleWs
with DefaultRestServiceConfigurationProvider
with HybrisEndpointProvider
with ProductServiceEndpointProvider /// collision, since HybrisEndpointProvider already defined the endpointKey !!!!!
}
}
Ich habe viel von Ihrem Beispiel gelernt, danke. – simou