web-dev-qa-db-ja.com

新しいオブジェクトの作成と依存性注入の違い

新しいオブジェクトの作成と依存性注入の違いは何ですか?詳しく説明してください。

23
TaherT

さて、新しいオブジェクトの作成は、可能な限り明示的です。目的のクラスの新しいインスタンスを作成します。

依存性注入は、必要な場所に参照を提供するメカニズムです。データベースへの接続プールを表すクラスを想像してみてください。通常、そのクラスのインスタンスは1つだけです。次に、その参照を、それを使用するすべてのクラスに配布する必要があります。ここで、依存性注入が役立ちます。SpringなどのDIフレームワークを使用することで、プールの1つのインスタンスがそれを必要とするクラスに注入されるように定義できます。

オブジェクトの作成と依存性注入を簡単に比較することはできないため、質問自体に答えるのは簡単ではありません...

16
f1sh

まあ、それらは正確に比較できるわけではありません。ある時点でクラスをインスタンス化して、常に新しいオブジェクトを作成する必要があります。依存性注入には、新しいオブジェクトの作成も必要です。

依存性注入は、使用するクラスまたはテストするクラスによって使用されるインスタンスの動作を制御または検証する場合に実際に役立ちます。 (テスト駆動開発の場合、依存性注入は、最小の例を除くすべての場合に重要です)。

クラスHandleのオブジェクトを必要とするクラスHolderを想定します。これを行う従来の方法は、Holderインスタンスに作成して所有させることです。

class Holder {
    private Handle myHandle = new Handle();
    public void handleIt() {
        handle.handleIt();
    }
}

ホルダーインスタンスはmyHandleを作成し、クラス外の誰もそれを取得できません。場合によっては、ユニットテストがその1つであり、Handleインスタンスを作成せずにHolderクラスをテストすることはできないため、これは問題になります。Handleインスタンスは、他の多くのクラスやインスタンスに依存する可能性があります。これにより、テストが扱いにくく面倒になります。

たとえばコンストラクターにHandleインスタンスを挿入することにより、外部の誰かがインスタンスの作成を担当するようになります。

class Holder {
    private Handle myHandle;

    public Holder(Handle injectedHandle) {
        myHandle = injectedHandle;
    }

    public void handleIt() {
        handle.handleIt();
    }
}

ご覧のとおり、コードはほぼ同じで、Handleはまだプライベートですが、Holderクラスは外部との結合が大幅に失われているため、多くのことが簡単になります。また、Holderクラスをテストする場合、実際のインスタンスの代わりにモックまたはスタブオブジェクトを挿入して、Holder、その呼び出し元、およびハンドル間の相互作用を検証または制御することができます。

実際の注入は、他の場所、通常は「メイン」プログラムで行われます。プログラミングなしでそれを行うのに役立つフレームワークは複数ありますが、基本的にこれは「メイン」プログラムのコードです。

...
private Handle myHandle = new Handle(); // Create the instance to inject
private Handler theHandler = new Handler(myHandle); // Inject the handle
...

本質的に、インジェクションは単なるsetメソッドにすぎません。そしてもちろん、上記の簡単な例のようにコンストラクターではなく、それを使用してインジェクションメカニズムを実装できます。

25
thoni56

もちろん、どちらもオブジェクトを作成します。違いは、誰が作成の責任者であるかです。依存関係を必要とするクラスなのか、それともコンポーネントの依存関係を配線するSpringのようなコンテナなのか。依存関係は、別の(通常はXML)構成ファイルで構成します。

それは本当に関心の分離です。クラスは、これ、これ、およびこのコンポーネントが必要だと言っているので、正しく機能します。クラスは、コンポーネントを取得する方法を気にしません。それらを別の構成ファイルを使用してクラスにプラグインします。

例を挙げると、支払いモジュールが必要なショッピングクラスがあることを考えてみましょう。使用する支払いモジュールをハードコーディングする必要はありません。これを実現するには、制御を逆にします。コンテナの設定ファイルで数回のキーストロークで、使用済みの支払いモジュールを変更できます。力は、Javaコードに触れていないことです。

16
Petar Minchev

依存性注入は、アプリケーションに構成可能性のレイヤーを追加します。ある意味で、オブジェクトの構築をハードコーディングする場合は、アプリを再構築して再デプロイする必要がありますが、依存性注入を使用する場合は、再構築して再デプロイすることなく、XMLを再構成して動作を変更できます。これにより多くの結びつきと労力を節約できるさまざまなユースケースがあります。

3
carlsborg

制御の反転コンテナを使用して依存性注入を実行する場合、コンテナは開発者ではなくオブジェクトを作成します。これは、コンテナがこれらのオブジェクトを他のオブジェクトに「注入」できるようにするために行われます。

2
Bozho