web-dev-qa-db-ja.com

5歳児への依存性注入の説明方法

依存性注入 を説明する良い方法は何ですか?

Googleでいくつかのチュートリアルを見つけましたが、読者がJava初心者であると想定するチュートリアルはありません。これを初心者にどのように説明しますか?

208
user198313

5歳児に依存性注入を行います。

自分で冷蔵庫から物を取り出すと、問題が発生する可能性があります。ドアを開けたままにしたり、ママやパパが欲しくないものを手に入れたりするかもしれません。私たちが持っていないものや期限切れのものを探しているかもしれません。

あなたがしなければならないことは、「昼食時に何か飲む必要がある」という必要性を述べることです。そして、私たちはあなたが座って食事をするときに何かを確実にします。

790
John Munsch

これはどうですか?

クラスEmployeeがあり、この従業員にAddressがある場合、次のようにEmployeeクラスを定義できます。

class Employee {
    private Address address;

    // constructor 
    public Employee( Address newAddress ) {
        this.address = newAddress;
    }

    public Address getAddress() {
    return this.address;
    }
    public void setAddress( Address newAddress ) {
        this.address = newAddress;
    }
}

これまでのところ、すべてが正常に見えます。

このコードは、従業員と彼の住所の間のHAS-A関係を示しています。

さて、このHAS-A関係がそれらの間に依存関係を作成しました。問題はコンストラクタ内にあります。

Employeeインスタンスを作成するたびに、Addressインスタンスが必要です。

 Address someAddress = ....
 Employee oscar = new Employee( someAddress ); 

この方法での作業は、単体テストを実行するときに問題になります特に.

主な問題は、ある特定のオブジェクトをテストする必要がある場合、他のオブジェクトのインスタンスを作成する必要がある場合、そしておそらくotherオブジェクトのインスタンスを作成する必要がある場合です。チェーンが管理不能になる可能性があります。

これを回避するには、コンストラクタを次のように変更します。

  public Employee(){
  }

引数なしのコンストラクタを使用します。

その後、いつでもアドレスを設定できます。

 Address someAddress = ....
 Employee oscar = new Employee();
 oscar.setAddress( someAddress ); 

これで、いくつかの属性がある場合、またはオブジェクトを作成するのが難しい場合、これはドラッグになる可能性があります。

しかし、これについて考えてみましょう。Department属性を追加するとしましょう。

  class Employee {
      private Address address;
      private Department department;

  ....

300人の従業員がいて、全員が同じ部門を持っている必要があり、さらに同じ部門を他のオブジェクト(部門の会社リスト、各部門の役割など)で共有する必要がある場合have etc)すると、Departmentオブジェクトの可視性に苦労し、オブジェクトのすべてのネットワークで共有するのが難しくなります。

Dependency Injectionとは何ですか? "inject"コード内のこれらの依存関係。ほとんどのフレームワークでは、外部ファイルでどのオブジェクトを注入するかを指定することでこれを行うことができます。

架空の依存関係インジェクターのプロパティファイルを想定します。

  #mock employee
  employee.address = MockAddress.class
  employee.department = MockDepartment.class

  #production setup 
  employee.address = RealAddress.class
  employee.department = RealDepartment.class

特定のシナリオで何を注入するかを定義します。

Dependency Injectorフレームワークは、正しいオブジェクトを設定するため、setAddressまたはsetDepartmentをコーディングする必要はありません。これは、リフレクションによって、またはコード生成または他の手法によって行われます。

したがって、次回Employeeクラスをテストする必要があるときは、すべてのテストのすべてのセット/取得をコーディングすることなく、モックAddressおよびDepartmentsオブジェクトを注入できます。さらに良いことに、実動コードにrealAddressおよびDepartmentオブジェクトを注入しても、テストされたとおりにコードが機能するという自信があります。

それはほとんどそれについてです。

それでも、私はあなたが要求したように、この説明が5歳に適しているとは思わない。

あなたがそれがまだ有用であることを願っています。

93
OscarRyz

クラスを書くとき、他のオブジェクトを利用するのは自然なことです。たとえば、データベース接続、または使用する他のサービスがある場合があります。これらの他のオブジェクト(またはサービス)は依存関係です。コードを記述する最も簡単な方法は、他のオブジェクトを作成して使用することです。しかし、これは、オブジェクトがそれらの依存関係に対して柔軟性のない関係を持っていることを意味します。オブジェクトを呼び出している理由に関係なく、オブジェクトは同じ依存関係を使用します。

より強力な手法は、オブジェクトを作成し、使用する依存関係を提供できるようにすることです。したがって、使用するデータベース接続を作成し、それをオブジェクトに渡すことができます。このようにして、異なる時間に異なる依存関係を持つオブジェクトを作成し、オブジェクトをより柔軟にすることができます。これは、オブジェクトに依存関係を「注入」する依存性注入です。

ところで:flickrの写真を使用して概念を説明する現代のプレゼンテーションスタイルでは、麻薬で自分自身を撃つ中毒者がこれを説明できます。ああ、待って、それは注入依存関係です... OK、ごめん、悪い冗談。

24
Ned Batchelder

私は簡単なチュートリアルを知りませんが、ほとんどあなたに与えることができます 25 250ワード以下のバージョン:

依存性注入では、オブジェクトは既に知っていることに基づいて独自のコンポーネントを構成するのではなく、オブジェクトはより高いレベルのロジックで構成され、組み込みの事前知識を持っていないコンポーネントを呼び出します。目的は、オブジェクトをコンポーネントに、アプリケーションをより少なくし、構成タスクをより高いレベルに再配置することです。これにより、オブジェクトが将来または別の構成で役立つ可能性が高くなります。

テストに向いている、アプリケーションを修正する時が来たときは良い。典型的な実装では、構成をXMLに配置し、フレームワークを使用してクラスを動的にロードします。

10
DigitalRoss

新しい任天堂が与えられたら、ボタンとタッチスクリーンを使用してゲームをプレイできます。

しかし、任天堂の工場では、それらを組み立てる方法を知る必要があります。

工場の賢い人たちがニンテンドーDSを持ち出すとき、それは内部では異なりますが、それを使用する方法はまだわかります。

7
WW.