はじめに
今回はJavaを学習した中で出会ったDI(dependency Injection)について記事を書いていきます。
DI(dependency Injection)とは
DI(Dependency Injection)とは、クラス同士の結合度を低くする設計思想を指します。ここで述べる結合度とは、クラスAがクラスBに対してどれだけ依存しているかを表す概念です。
結合度が高い状態とは、クラスAがクラスBを呼び出すときに、クラスBのインスタンス(オブジェクト)を毎回生成して利用する状態を指します。この場合、クラスAはクラスBがなければ動作できません。そのため、クラスBに変更があった場合、クラスAにも大きな影響を及ぼします。
一方、DIを用いて結合度が低い状態とは、クラスAがクラスBを呼び出す際に、一度クラスCを経由することです。クラスCを介入させることで、クラスAとクラスBは独立した状態で動作できるようになります。これにより、いずれかのクラスに変更があった場合でも、影響を最小限に抑えることが可能となります。
例えるなら
DIの概念をわかりやすくするために、スマートホームとアシスタントAIを用いて説明します。
AIアシスタントが備わったスマートホームを想像してください。家には既にAlexというサービスと直接契約してます。しかし途中から利用するAIを変更したくなりました。ですがAlexにすべてを任せていたため、簡単に変更ができなくなっています。
上記のたとえ話の中でDIを適用した状態とは、利用者とAIサービスの間に中間業者を入れた状態です。
これから利用者は中間業者とやり取りすることになります。この状態なら、中間業者が各サービスを上手に調整してくれるので、サービスを変更しても大きな影響がありません。
プログラム例
DIを利用したプログラムを以下に示します。
メインクラスはそれぞれのAIを備えたスマートホームです。
コード中の⓵の部分が利用するAIの宣言。コード中⓶の部分がAIを利用するサービスを宣言します。
コード⓶では利用したいAIを中間業者に渡しています。
中間クラスがAIを利用できる状態にし、コード⓷ではAIを利用できるようにしています。
import AssistantAI.Alex;
import AssistantAI.Assistant;
import AssistantAI.Siro;
public class Main {
public static void main(String[] args) {
// Alexを利用したスマートホーム
Assistant Alex = new Alex(); //・・・⓵
Service Service1 = new Service(Alex);//・・・⓶
Service1.Hello(); //・・・⓷
System.out.println();
// Siroを利用したスマートホーム
Assistant Siro = new Siro();
Service Service2 = new Service(Siro);
Service2.Hello();
}
}
以下はスマートホームで利用するAIのクラスです。
メインからAIクラスは呼び出さず中間クラスを経由します。
package AssistantAI;
public interface Assistant {
void greeting();
}
package AssistantAI;
public class Alex implements Assistant {
@Override
public void Greeting() {
System.out.println("こんにちは。私は Alex です。");
System.out.println("Riverから生まれました。");
}
}
package AssistantAI;
public class Siro implements Assistant {
@Override
public void greeting() {
System.out.println("こんにちは。私は Siro です。");
System.out.println("Fruitから生まれました。");
}
}
以下はメインクラスにAIクラスを渡すための中間クラスです。中間クラスがメインクラスの代わりにAIクラスをオブジェクト化します。メインクラスはオブジェクト化したものを扱います。
import AssistantAI.Assistant;
public class Service {
private Assistant AssistantAI;
public Service(Assistant AssistantAI) {
this.AssistantAI=AssistantAI;
}
public void Hello() {
AssistantAI.Greeting();
}
}
メインクラスを実行すると以下の結果が得られます。中間クラスがメインクラスとAIクラスの間に入ってオブジェクトのやり取りをするので利用するAIクラスを変更しても動きます。
こんにちは。私は Alex です。
Riverから生まれました。
こんにちは。私は Siro です。
Fruitから生まれました。
おわりに
以上からDIを簡単にまとめると次の通りになります。
- オブジェクトを関節的にやり取りすること
- それぞれのクラスが独立していること
- クラスの修正がしやすいこと
以上がDIに対する私の認識でした。誤り等あればご指摘ください。
参考文献
- Dependency Injection :: Spring Framework
- 土岐孝平 著, "プロになるためのSpring入門 ――ゼロからの開発力養成講座",
技術評論社, pp.38-47