2016-12-28 5 views
4

ScalaでDI用に関数とCakeパターンを使用することの違いについては、私は不思議でした。私は次のような理解を思いつき、この理解が正しいかどうかを知りたいと思います。CakeパターンとScalaでの関数の違い - Cakeパターンはなぜ便利ですか?

依存グラフを想像してみましょう。

1)関数をビルディングブロックとして使用すると、グラフはノードとしての関数とエッジとしてのパラメータで構成されます。

2)形質をビルディングブロック(Cakeの場合)として使用すると、グラフはノードとしての特性とエッジとしての抽象的なメンバーで構成されます。

ケーキパターンの目的は何ですか?なぜ2が1より良いのですか?コースグラインディングです。グラフ-1は、関数を特性にグループ化することで簡略化することができます。関連概念のグループ化/クラスタリングは圧縮の一形態であり、理解を生み出します(私たちは理解を深めるために頭の中で少ないものを保持する必要があります)。ここで

は(パッケージシステムVSケーキの間に)異なる比較である:

ケーキは、パッケージに関連する機能をグループ化に似ていますが、それは名前空間(パッケージ/オブジェクト)を使用しているのでそれを超えて依存関係が難しいことになり-wired、Cakeはパッケージ/オブジェクトを特質に置き換え、importは自己型の注釈/抽象メンバで置き換えています。パッケージとCakeパターンの違いは、依存関係の実際の実装は、Cakeを使用して変更できますが、パッケージを使用するときは変更できないということです。

これらの類推が意味をなさないかどうかわかりませんが、もし正しくない場合は、私を修正してください。そうなら、私を安心してください。私はまだケーキのパターンの周りに私の頭を包み込み、私はすでに理解している概念(関数、パッケージ)に関連付けることを試みています。

+0

少しのコードスニペットにexampleを付けることができますか?関数の実装方法はどうですか? –

+0

どういう意味ですか?どのような機能の実装ですか?多分あなたはこれを意味するでしょう: 'foo'が' x'に依存している 'def foo(x)= {...}'は、あなたが意味するものですか?したがって、 'foo'はノードであり、' x'は依存グラフのエッジです。 – jhegedus

答えて

1

依存性注入(DI)は、getter/setters(これは、あなたが関数を意味すると考える)やコンストラクタparamsで一般的に行われます。 getter/setterのアプローチは次のようになります。

trait Logger { 
    // fancy logging stuff 
} 

class NeedsALogger { 
    private var l: Logger = _ 
    def logger: Logger = l 
    def logger_=(newLogger: Logger) { 
    l = newLogger 
    } 
    // uses a Logger here 
} 

私はゲッター/セッターのアプローチが本当に好きではありません。依存関係が注入されるという保証はありません。特定のDIフレームワークを使用する場合、何かが注入されることを強制することができますが、DIはもはやあなたのフレームワークに無関心ではありません。あなたは、コンストラクタのアプローチを使用している場合、我々は(関係なく、フレームワークの)インスタンス化したときに今、依存性が提供されなければならない:今

class NeedsALogger(logger: Logger) { 
    // uses a Logger here 
} 

、どのようにあるケーキ柄フィット?まずは、ケーキ柄に私たちの例を適応してみましょう:

class NeedsALogger { 
    logger: Logger => 
    // Uses a Logger here 
} 

はの約logger: Logger =>をお話しましょう。これは自己タイプであり、Loggerを拡張することなく、Loggerのメンバーを範囲に入れるだけです。 NeedsALoggerLoggerではないので、私たちはそれを拡張したくありません。ただし、NeedsALoggerにはLoggerが必要です。これは、セルフタイプで達成したものです。 NeedsALoggerを作成する際には、Loggerを提供する必要があります。使用法は次のようになります。

trait FooLogger extends Logger { 
    // full implementation of Logger 
} 

trait BarLogger extends Logger { 
    // full implementation of Logger 
} 

val a = new NeedsALogger with FooLogger 
val b = new NeedsALogger with BarLogger 
val c = new NeedsALogger // compile-time error! 

ご覧のとおり、いずれの方法でも同じことが成り立ちます。多くのDIについては、コンストラクターのアプローチで十分です。したがって、あなたの好みに基づいて選ぶことができます。私は個人的には自分のタイプやケーキパターンが好きですが、私も多くの人がそれを避けています。

ケーキパターンについて詳しくは、thisをチェックしてください。あなたがもっと知りたいのなら、それは次のステップです。

関連する問題