依存関係とは
依存関係とは、あるクラスが単体では動作せず、他のクラスに処理を任せている状態を指します。
例えば、注文処理を行うクラスが決済処理を別のクラスに委ねている場合、そのクラスは決済クラスに依存していると言えます。
public class OrderService {
private final PaymentService paymentService;
public OrderService(PaymentService paymentService) {
this.paymentService = paymentService;
}
}
この例では、OrderService は PaymentService がなければ動作しません。
つまり、OrderService は PaymentService に依存しています。
DIとは
DI(Dependency Injection:依存性注入)とは、クラスが必要とする依存関係を、自分で生成するのではなく外部から渡す仕組みのことです。
なぜDIが必要なのか
前の例では、依存関係をクラス内で生成していました。
public class OrderService {
private PaymentService paymentService = new PaymentService();
}
このような書き方では、PaymentService が固定されてしまい、柔軟性が失われます。
- 別の実装に差し替えられない
- テスト時にモックを使えない
- クラス同士が強く結びつく(密結合)
DIによる解決
DIでは、依存関係を外から渡します。
public class OrderService {
private final PaymentService paymentService;
public OrderService(PaymentService paymentService) {
this.paymentService = paymentService;
}
}
OrderService は PaymentService を自分で生成せず、外部から渡されたものをそのまま利用します。
そのため、「どの実装を使うか」や「どのように生成されるか」を意識する必要が少なくなります。
コンストラクタの役割
コンストラクタの役割は、クラスが必要とする依存関係を受け取ることです。
public class OrderService {
private final PaymentService paymentService;
// コンストラクタ:依存関係を受け取る
public OrderService(PaymentService paymentService) {
this.paymentService = paymentService;
}
}
このようにすることで、
- 必要な依存関係がコード上に明示される
- 自クラス外から渡されたオブジェクトを利用する構造になる
つまりコンストラクタは、依存関係の受け取り口であり、「このクラスは何に依存しているか」を明確にするものです。
コンストラクタに書く基準
コンストラクタに書くべきかどうかは、そのオブジェクトを自クラス内で生成するかどうかで判断します。
書くべきもの
- 自クラス外から渡してもらうべきもの(自分で生成しないもの)
書かなくてよいもの
- クラス内で完結する処理
- 自分で生成して問題ない軽いオブジェクト
- 単なる値(設定値など)
まとめ
コンストラクタは単なる初期化ではなく、依存関係を外部から受け取るための仕組みです。
そのオブジェクトを自クラス内で生成するのか、外から受け取るのかを基準に判断します。