配線を1箇所変える例
ここでは「interface で十分では?」に対して、実装切替時の差を受注と商品の例で具体的に示します。
なぜ interface だけでは足りないのか
interface は「型の約束」を作りますが、 「どの実装を使うかをどこで決めるか」までは決めません。 そのため、実装選択が各クラスに散らばると、変更時に修正箇所が増えます。
interface だけの例
受注処理と在庫確認で同じ interface を使っていても、実装生成が分散しているケースです。
interface ProductGateway {
Product findByCode(String code);
}
class OrderService {
private final ProductGateway gateway = new ProductDbGateway();
}
class StockService {
private final ProductGateway gateway = new ProductDbGateway();
}
この状態で「商品情報を外部APIから取得」に変更すると、
new ProductDbGateway() を書いた場所を探して直す必要があります。
DIで配線を集約した例
利用側は interface を受け取るだけにし、実装選択を設定クラスへ集約します。
class OrderService {
private final ProductGateway gateway;
OrderService(ProductGateway gateway) { this.gateway = gateway; }
}
class StockService {
private final ProductGateway gateway;
StockService(ProductGateway gateway) { this.gateway = gateway; }
}
@Configuration
class GatewayConfig {
@Bean
ProductGateway productGateway() {
return new ProductDbGateway();
}
}
1箇所変更の具体例
ここで外部APIへ切り替える場合、変更は原則この設定1箇所です。 利用側クラス(受注・在庫)は触りません。
@Configuration
class GatewayConfig {
@Bean
ProductGateway productGateway() {
// 変更前: return new ProductDbGateway();
return new ProductApiGateway();
}
}
これが「配線を1箇所変えればいい」の意味です。 interface は前提として必要ですが、 DI で配線を集約しないと修正箇所は減りません。
Java 1.4 時代の感覚で言うと、Factory/Assembler を1箇所に集める設計を、フレームワークが標準化したものが現在の DI コンテナです。