l

o

a

d

i

n

g

.

.

.

GoF以外のプログラミング・デザインパターン #24 Dependency Injection

2025/12/15

プログラミング 学習

t f B! P L
eyecatch 「Dependency Injection(依存性の注入)」は、 オブジェクト同士の結合を緩めて、テストや拡張をしやすくするための設計パターンです。

基本の考え方

・クラスが他のクラス(依存対象)を 自分でnewしない ・外部から「必要な依存オブジェクト」を 注入(Injection) してもらう ・結果として、クラス同士の依存関係を 疎結合(loose coupling) にできる

用語解説

依存(Dependency)

クラスが使う他のオブジェクト。

注入(Injection)

外部からその依存を渡すこと。

目的

クラス間の結合をゆるめ、柔軟でテストしやすい設計にする。

サンプルコード1: Before After

依存が強いコード

class EmailService { send(message) { console.log("📧 Email sent:", message); } } class UserNotifier { constructor() { this.emailService = new EmailService(); // ← 依存を内部で固定している } notify() { this.emailService.send("Welcome new user!"); } } const notifier = new UserNotifier(); notifier.notify();

このコードの問題点

・UserNotifier が EmailService を直接生成している。 ・このため、もしSMSやSlack通知に変えたい場合、クラスの中身を書き換える必要がある。

改良版:Dependency Injectionを使う

class EmailService { send(message) { console.log("Email sent:", message); } } class SMSService { send(message) { console.log("SMS sent:", message); } } class UserNotifier { constructor(service) { this.service = service; // ← 依存を外部から注入 } notify() { this.service.send("Welcome new user!"); } } // 依存の切り替えが自由にできる const emailNotifier = new UserNotifier(new EmailService()); const smsNotifier = new UserNotifier(new SMSService()); emailNotifier.notify(); smsNotifier.notify();

ポイント解説

・UserNotifier は 抽象的な「sendできるもの」 に依存。 ・具体的な通知方法は外から与える。(=依存を注入する)

依存性注入の3つの方法

方法 説明
コンストラクタ注入 コンストラクタの引数で依存を受け取る(最も一般的)
セッター注入 `setService()` のようなメソッドで後から注入
インターフェース注入 外部のDIコンテナ(例:Spring)によって自動的に注入

サンプルコード2 : DIコンテナ風実装

class Container { constructor() { this.bindings = new Map(); } register(key, ClassRef) { this.bindings.set(key, ClassRef); } resolve(key) { const ClassRef = this.bindings.get(key); return new ClassRef(); } } // 依存を登録 const di = new Container(); di.register("notificationService", EmailService); di.register("userNotifier", () => new UserNotifier(di.resolve("notificationService"))); // 依存を自動解決して利用 const notifier = di.resolve("userNotifier"); notifier.notify();

メリット

・クラス間の結合度が低くなる(差し替えが容易) ・テストがしやすくなる(モックやスタブを注入可能) ・アプリケーションの拡張性が高まる

デメリット

・小規模アプリでは逆に複雑になる ・依存関係の把握が難しくなる(DIコンテナを多用すると特に) ・ランタイムエラーになりやすい(型安全ではない言語では注意)

あとがき

プログラミングの設計で重要なのは、なんといっても「依存度を下げる」という点でしょう。 Dependency Injectionは、まさにそのための設計思想パターンですね。 できる限りクラス分けして、それぞれを独立させることで、その後の拡張などが便利になるのが、サンプルコードを見て理解できると思います。 ただ、DIコンテナというクラス構造の階層が深くなるリスクがあるので、全体設計を事前にしてから、DIコンテナ利用を設置するのはどこが適切かを見極めないと、逆に分かりずらく、管理しずらい設計になりかねないという点を、理解しておく必要もあります。 そんな加減が必要なデザインパターンでした。

人気の投稿

このブログを検索

ごあいさつ

このWebサイトは、独自思考で我が道を行くユゲタの少し尖った思考のTechブログです。 毎日興味がどんどん切り替わるので、テーマはマルチになっています。 もしかしたらアイデアに困っている人の助けになるかもしれません。

ブログ アーカイブ