##本ページの目的
色々な解説を見てもしっくりこない為自分を納得させるために書く。
##DIの概要
まずは教科書的な書き方だと
「DIはデザインパターン1の一つである"Inversion of Control Principle"(制御の反転の原則)」を実現する。
コンポーネントを構成するインスタンスの生成と依存関係の解決をソースコードから分離することが出来る。
(Spring徹底入門より 株式会社NTTデータ著)
何を言っているのかわからないですね。
とりあえず理解しやすいところから考えるようにしましょう。
##DIのメリット
とりあえず何をどうするかは置いといて、DIによってなにが良くなるのかというと
・クラス間の依存性が下がる = クラス間の結合が疎になる(疎結合になる)
・↑によってクラスなどの再利用が簡単になる
・↑によって単体テストなどがやりやすくなる
という事らしいです。
なにやら依存性という言葉が何度も出ているため、ここに核心がありそうです。
ではプログラミングにおける「依存性」とはなんなのでしょうか?
##依存性とは
こちらも教科書的な言葉を使うと、
「あるモジュールが別のモジュールの内部動作によって変化したり依存したりする = 依存関係にあるモジュールの仕様を変更した場合、モジュールの内容が壊れる可能性が大きい」
実際にJava言語などで依存性が高い構成とは
・あるクラスのメソッド内で別のクラスのインスタンスをnewして生成している
・あるクラスのメソッドの引数として他のクラスのインスタンスを使用している
といったものが挙げられます。
具体的なコードだと
class Hoge{
public void hoge(){
Fuga fuga = new Fuga();
}
}
かなり具体的になってきましたね。
あるクラスで他のクラスをnewして使用した場合、newするクラスのコンストラクタなどの変更あった場合、呼び出し元のメソッドも変更しなければいけないことは想像できると思います。
そのほかにもインスタンスを生成するクラス内でメソッドを変更した場合も呼び出し元の処理がぐちゃぐちゃになってしまいます。
この問題の解決方法としては、呼び出し元のクラスでは、実装クラスをnewしてインスタンスを生成するのではなく、インターフェイスを利用するようにして、実際にnewするクラスはインターフェイスを継承したクラスにする、というものです。
pulic interface Fuga{
int a;
void foo();
}
pulic HogeFuga implements Fuga{
int a;
void foo(){
fugafuga;
};
}
class Hoge{
public void hoge(){
Fuga fuga = new HogeFuga();
}
}
この方法を用いることで、インターフェイスをimplementしたクラスを自由に使用できるようになるため、依存関係を低下させることが出来ます。
しかし、結局インターフェイスクラスはnewすることはできない為、implementしたサブクラスを呼び出し元でnewする記述が必要です。
そこで、その関係性をxmlファイルやアノテーションを用いて記述する
↓
これが「DI」
##具体的なDIの方法
####セッターインジェクション
class Hoge{
Fuga fuga;
public void hoge(){
}
public void setFuga(Fuga fuga){
this.fuga = fuga;
}
}
この時、setFugaクラスに渡すのはFugaクラスをimplementしたクラスであればなんでも良く、Hogeクラスは実際にどのクラスを使用しているかは関知しない。
####アノテーションインジェクション
Springを使うとこちらの方が主流でしょうか
class Hoge{
@Autowired
protected Fuga fuga
public void hoge(){
}
}
##まとめ
DIってなに? = 使用するクラスの縛りを減らしたい!
-
オブジェクト指向の言語での設計ノウハウ集 ↩