Vla*_*eev 10 dependency-injection scala cake-pattern
我尝试在我的项目中使用蛋糕模式并且非常喜欢它,但是有一个困扰我的问题.
当所有组件具有相同的生命周期时,蛋糕模式易于使用.您只需定义多个traits-components,通过traits-implementation扩展它们,然后将这些实现组合在一个对象中,并通过自我类型自动解析所有依赖项.
但是假设您有一个组件(具有自己的依赖项),可以根据用户操作创建该组件.无法在应用程序启动时创建此组件,因为它尚无数据,但在创建时应具有自动依赖性解析.这种组件关系的一个例子是主GUI窗口及其复杂的子项(例如笔记本窗格中的选项卡),它们是根据用户请求创建的.主窗口是在应用程序启动时创建的,当用户执行某些操作时会创建其中的一些子窗格.
这很容易在像Guice这样的DI框架中完成:如果我想要一些类的多个实例,我只需注入一个Provider<MyClass>; 然后我get()在该提供程序上调用方法,并MyClass自动解析所有依赖项.如果MyClass需要一些动态计算的数据,我可以使用辅助注入扩展,但结果代码仍然归结为提供者/工厂.相关概念,范围,也有帮助.
但我想不出用蛋糕模式做这件事的好方法.目前我正在使用这样的东西:
trait ModelContainerComponent { // Globally scoped dependency
def model: Model
}
trait SubpaneViewComponent { // A part of dynamically created cake
...
}
trait SubpaneControllerComponent { // Another part of dynamically created cake
...
}
trait DefaultSubpaneViewComponent { // Implementation
self: SubpaneControllerComponent with ModelContainerComponent =>
...
}
trait DefaultSubpaneControllerComponent { // Implementation
self: SubpaneViewComponent with ModelContainerComponent =>
...
}
trait SubpaneProvider { // A component which aids in dynamic subpane creation
def newSubpane(): Subpane
}
object SubpaneProvider {
type Subpane = SubpaneControllerComponent with SubpaneViewComponent
}
trait DefaultSubpaneProvider { // Provider component implementation
self: ModelContainerComponent =>
def newSubpane() = new DefaultSubpaneControllerComponent with DefaultSubpaneViewController with ModelContainerComponent {
val model = self.model // Pass global dependency to the dynamic cake
}.asInstanceOf[Subpane]
}
Run Code Online (Sandbox Code Playgroud)
然后我混合DefaultSubpaneProvider我的顶级蛋糕并注入SubpaneProvider所有需要创建子窗格的组件.
这种方法的问题是我必须手动将依赖关系(modelin ModelContainerComponent)从顶级蛋糕传递到动态创建的蛋糕.这只是一个简单的例子,但可以有更多的依赖关系,并且还可以有更多类型的动态创建的蛋糕.它们都需要手动传递依赖关系; 此外,某些组件接口的简单更改可能会导致多个提供程序中的大量修复.
是否有更简单/更清洁的方法来做到这一点?蛋糕模式中如何解决这个问题?
您是否考虑过以下替代方案:
在 Scala 中使用内部类,因为它们会自动访问其父类成员变量。
在基于参与者的应用程序中重构您的应用程序,因为您将立即受益:
拥有更多代码可能会有助于提供更好的解决方案,您可以分享代码的编译子集吗?
| 归档时间: |
|
| 查看次数: |
775 次 |
| 最近记录: |