依存関係逆転(DIP: Dependency Inversion Principle)メモ
- 前提:
- 「不安定→安定」の依存になっている場合は、原則通りなのでOK。
- 個別コードが、ライブラリを呼び出す場合など。
- アプリケーションによっては、「安定→不安定」の依存になる場合がある。
- Webアプリケーションサーバ(安定:フレームワーク側)が、個別のアプリケーション(不安定)を呼び出す場合など。
- この場合は、抽象を一枚噛ませて安定させる。
- 「不安定→安定」の依存になっている場合は、原則通りなのでOK。
「2. コールバッククラスの登録」を例にしたサンプル:
■フレームワークレイヤ
// コールバックされるインターフェース interface CallbackableIF { int x; int y; void calc(); // ←ここの実装内容が、上位層に依存するとする。 }
// メソッドの呼び口を用意するけど、その具体的な実装内容は上位にお任せする class Callbacker { public void callback(CallbackableIF callbackableImpl) { callbackableImpl.calc(); } }
↑ここまでフレームワーク(下位層)
↓ここからユーザ側の個別コード(上位層)
■具象レイヤ
// 上記インターフェースの実装その1 class CallbackImplA implements CallbackableIF { public CallbackImplA(int x, int y) { this.x = x; this.y = y; } public void calc() { System.out.println(x + y); // 足し算で実装 } }
// 上記インターフェースの実装その2 class CallbackImplB implements CallbackableIF { public CallbackImplB(int x, int y) { this.x = x; this.y = y; } public void method() { System.out.println(x * y); // 掛け算で実装 } }
■設定(実行)レイヤ
public class CallbackSample { public static void main(String args[]) { int x = 10; int y = 20; CallbackableIF callbackableImplA = new CallbackImplA(x, y); CallbackableIF callbackableImplB = new CallbackImplB(x, y); Callbacker callbacker = new Callbacker(); callbacker.callback(callbackableImplA); callbacker.callback(callbackableImplB); } }
■ UML
[Initializer]──<<create>>──→[CallbackImpl]……|>[Callbackable] │ │ └────<<create>>───→[Framework]◆──────┘