第21回 DI
今回のテーマは「DI」です。 前回は、クラスとクラスを疎結合させるために、ファクトリを用いました。 今回はDIと呼ばれる手法を使って、クラス間の依存関係を解消しましょう。 それでは「DIとは何ぞや」というところから始めます。 DIとはDependency Injectionの略で、「依存性注入」と訳されます。 かつては「IoC(Inversion of Control)」と呼ばれ「制御の反転」と訳されていましたが、 これでは意味がよくわからないということで、Dependency Injectionという名称になったそうです。
では、依存性の注入とは具体的にどういう処理を行うのでしょうか。 簡単なプログラムを使って説明していきます。
public class Player { public void play() { System.out.println("ウォームアップします。"); Badminton badminton = new Badminton(); badminton.play(); System.out.println("クールダウンします。"); } }
public class Badminton { public void play(){ System.out.println("バドミントンして遊びます。"); } }
再び登場のPlayerクラスとBadmintonクラスです。
BadmintonクラスがないとPlayerクラスはコンパイルさえできません。
では、依存性を注入するためにコードを変更していきます。
まず前回と同じようにSportsインターフェースを用意します。
public interface Sports { void play(); }
Sportsインターフェースの具象クラスを作成します。
public class MockSports implements Sports { @Override public void play() { System.out.println("開発途中です。"); } }
public class Badminton implements Sports { @Override public void play() { System.out.println("バドミントンして遊びます。"); } }
Playerクラスには、Sports型のフィールドを持たせて、そのアクセサメソッドを用意します。
play()メソッドはフィールドとして持ったSportsを使用するようにします。
public class Player { private Sports sports; public void play() { System.out.println("ウォームアップします。"); Sports sports = getSports(); sports.play(); System.out.println("クールダウンします。"); } public Sports getSports() { return sports; } public void setSports(Sports sports) { this.sports = sports; } }
最後にPlayerクラスを実行するクラスを作成します。
ここでPlayerクラスに対する、Sportsインターフェースの具象クラスを設定します。
public class Main { public static void main(String[] args) { Player player = new Player(); player.setSports(new Badminton()); player.play(); System.out.println(); player.setSports(new MockSports()); player.play(); } }
以上の構成により、PlayerクラスとBadmintonクラスの依存関係が解消されました。
依存性の注入とは、あるオブジェクトが使用するオブジェクトを外部で設定するということなのです。
今回のようにセッターを用いた注入を、特にセッター・インジェクションと呼びます。
他にはコンストラクタ・インジェクションと呼ばれるやり方もあり、インスタンス生成時に依存性を注入します。
DIはEJB3.0に取り入れられ、標準化された技術になりました。
今後のJavaEEの開発では、意識せずともDIを使うことになっていくでしょう。