【发布时间】:2013-07-05 17:52:33
【问题描述】:
我尝试在我的项目中使用蛋糕图案并且非常喜欢它,但是有一个问题困扰着我。
当所有组件都具有相同的生命周期时,蛋糕模式很容易使用。您只需定义多个特征组件,通过特征实现扩展它们,然后将这些实现组合到一个对象中,并通过自类型自动解决所有依赖关系。
但是假设您有一个组件(具有自己的依赖项),它可以作为用户操作的结果来创建。该组件无法在应用程序启动时创建,因为它还没有数据,但它应该在创建时具有自动依赖解析。这种组件关系的一个例子是主 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]
}
然后我在我的顶级蛋糕中混合DefaultSubpaneProvider,并在所有需要创建子窗格的组件中注入SubpaneProvider。
这种方法的问题是我必须手动将依赖项(ModelContainerComponent 中的ModelContainerComponent)从顶级蛋糕向下传递到动态创建的蛋糕。这只是一个简单的例子,但可以有更多的依赖关系,也可以有更多类型的动态创建的蛋糕。它们都需要手动传递依赖项;此外,某些组件接口的简单更改可能会导致多个提供程序中的大量修复。
有没有更简单/更干净的方法来做到这一点?这个问题在蛋糕图案中是如何解决的?
【问题讨论】:
-
如果我的回答没有解决你的问题,我会重新删除。
-
类似的东西呢
-
trait ModelContainerComponentProxy extends ModelContainerComponent { def originalModelContainer: ModelContainerComponentProxy; def model = originalModelContainer.model}-- 至少可以解决显式传递所有组件内容的问题。 -
如何将 cake 与 MacWire 等 DI 框架一起使用? github.com/adamw/macwire
-
为什么需要演员阵容?你不能写 def newSubpane():SubPane = {}
标签: scala dependency-injection cake-pattern