私は自分のプロジェクトでケーキのパターンを使用しようとしましたが、とても気に入りましたが、気になる問題が 1 つあります。
Cake パターンは、すべてのコンポーネントの寿命が同じ場合に使いやすいです。複数の traits-component を定義し、traits-implementation によってそれらを拡張し、これらの実装を 1 つのオブジェクト内で結合するだけで、自己型を介してすべての依存関係が自動的に解決されます。
しかし、ユーザー アクションの結果として作成できる (独自の依存関係を持つ) コンポーネントがあるとします。このコンポーネントは、まだデータがないため、アプリケーションの起動時に作成できませんが、作成時に依存関係を自動解決する必要があります。このようなコンポーネントの関係の例は、ユーザーの要求に応じて作成されるメイン 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
サブペインを作成するために必要なすべてのコンポーネントを注入します。
このアプローチの問題は、依存関係 ( model
in ModelContainerComponent
) を最上位のケーキから動的に作成されたケーキに手動で渡す必要があることです。これは些細な例にすぎませんが、より多くの依存関係が存在する可能性があり、動的に作成されるケーキの種類も増加する可能性があります。それらはすべて、依存関係を手動で渡す必要があります。さらに、一部のコンポーネント インターフェイスを変更するだけで、複数のプロバイダーで大量の修正が行われる可能性があります。
これを行うためのより簡単でクリーンな方法はありますか? この問題はケーキパターン内でどのように解決されますか?