我尝试在我的项目中使用蛋糕模式,并且非常喜欢它,但是有一个困扰我的问题。

当所有组件的生命周期相同时,可以轻松使用蛋糕图案。您只需定义多个traits-components,通过traits-implementation扩展它们,然后将这些实现组合在一个对象中,并通过自类型自动解决所有依赖关系。

但是,假设您有一个组件(具有自己的依赖项),可以根据用户操作来创建它。无法在应用程序启动时创建此组件,因为尚无数据,但是在创建时应具有自动的依赖项解析。这种组件关系的一个示例是主GUI窗口及其复杂子项(例如,笔记本 Pane 中的选项卡),这些子项是根据用户请求创建的。主窗口是在应用程序启动时创建的,当用户执行某些操作时会在其中创建子窗口。

这可以在像Guice这样的DI框架中轻松完成:如果我想要某个类的多个实例,我只需注入(inject)Provider<MyClass>即可;然后我在该提供程序上调用get()方法,并且MyClass的所有依赖项都将自动解决。如果MyClass需要一些动态计算的数据,则可以使用辅助注入(inject)扩展,但是生成的代码仍然可以归结为提供者/工厂。相关概念,范围也有帮助。

但是我想不出一个使用蛋糕模式进行此操作的好方法。目前,我正在使用这样的东西:

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,并在需要创建子 Pane 的所有组件中注入(inject)SubpaneProvider

这种方法的问题在于,我必须手动将依赖项(model中的ModelContainerComponent)从顶级蛋糕传递到动态创建的蛋糕。这只是一个简单的示例,但是可能存在更多的依赖关系,并且还可能存在更多类型的动态创建的蛋糕。它们都需要手动传递依赖项。此外,对某些组件接口(interface)的简单更改会导致在多个提供程序中进行大量修复。

有没有更简单/更干净的方法可以做到这一点?如何在蛋糕模式下解决此问题?

最佳答案

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

  • 在Scala中使用内部类,因为它们会自动访问其父类成员变量。
  • 在基于actor的应用程序中重组您的应用程序,因为您将立即受益于:
  • 层次结构/监督
  • 监听组件的创建/死亡
  • 在访问可变状态
  • 时进行适当的同步

    提供更多代码来提供更好的解决方案可能会有所帮助,您可以共享代码的编译子集吗?

    关于具有不同生命周期的对象的Scala蛋糕模式,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/17525950/

    10-09 05:40