Scala蛋糕模式对象与不同的生命周期

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)从顶级蛋糕传递到动态创建的蛋糕.这只是一个简单的例子,但可以有更多的依赖关系,并且还可以有更多类型的动态创建的蛋糕.它们都需要手动传递依赖关系; 此外,某些组件接口的简单更改可能会导致多个提供程序中的大量修复.

是否有更简单/更清洁的方法来做到这一点?蛋糕模式中如何解决这个问题?

Edm*_*984 0

您是否考虑过以下替代方案:

  • 在 Scala 中使用内部类,因为它们会自动访问其父类成员变量。

  • 在基于参与者的应用程序中重构您的应用程序,因为您将立即受益:

    • 层级/监督
    • 监听组件的创建/死亡
    • 访问可变状态时正确同步

拥有更多代码可能会有助于提供更好的解决方案,您可以分享代码的编译子集吗?