依存関係逆転の原則

王林
リリース: 2024-08-26 06:32:31
オリジナル
581 人が閲覧しました

高レベルのモジュールは低レベルのモジュールに依存すべきではありません。どちらも抽象化に依存する必要があります。

抽象化は詳細に依存すべきではなく、詳細は抽象化に依存する必要があります。

例を通して、高レベルモジュール低レベルモジュールを理解しましょう:

Dependency Inversion Principle

Flipkart のような e コマース アプリでは、高レベルで ProductCatalog、PaymentProcessor、CustomerProfile に分類できます (これらは主要なビジネス機能の一部です)
これらのビジネス機能は、上の図に示されている他のモジュールに相互依存しています。

注: 上部のモジュールは、高レベルのモジュールと呼ばれるビジネス機能に近いです。
一番下のモジュールは、低レベルレベルのモジュール

と呼ばれる実装の詳細に近いものです。

低レベル モジュールは、SQLProductRepository、GooglePayService、WireTransfer、EmailSender、および VoiceDialer です。

CustomerProfile (高レベル モジュール) と通信モジュールだけを考慮すると、通信は低レベル モジュールですが、通信、EmailSender、および VoiceDialer だけを考慮すると、通信は高レベル モジュールになり、EmailSender と VoiceDialer は低レベルモジュール

ここでのポイントは、高レベルモジュールと低レベルモジュールの概念は絶対的なものではなく、相対的なものです

上の画像によると、ProductCatalog は SQLProductRepository に依存しています。つまり、高レベルのモジュールは低レベルのモジュールに依存していますが、これは直接

DIP の最初の定義と競合しています

ProductCatalog → SQLProductRepository の関係を取り上げて、さらに分析してみましょう。

リーリー リーリー
ProductCatalog は SQLProductRepository に直接依存しているため、これは明らかに DIP 定義 1 の違反です (定義によれば、

高レベルと低レベルのモジュールは両方とも抽象化に依存する必要があります

)定義 1 に従ってこれを修正しましょう:

インターフェース ProductRepository の作成

リーリー
SQLProductRepository でのこのインターフェイスの実装

リーリー
最後に、高レベル モジュール ProductCatalog については、その中で SQLProductRepository を直接インスタンス化すべきではありません

。同じために ProductFactory クラスを使用します

リーリーProductFactory を使用して SQLProductRepository をインスタンス化します

リーリー

参照オブジェクトは ProductRepository であることに注意してください。そのため、SQLProductRepository との密結合はありません

変更後の新しい依存関係は次のようになります

上記の変更はDIP定義1によるものです。Dependency Inversion Principle上記のコード変更は、DIP の 2 番目の定義にも準拠しています。つまり、抽象化は詳細に依存すべきではなく、詳細は抽象化に依存する必要があります。

上の画像からわかるように、SQLProductRepository は ProductRepository に依存しており、その逆ではありません。

これが、この原則が依存関係逆転の原則と呼ばれる理由です

依存関係の注入 VS 依存関係の反転

リーリー
依存関係の注入について:

ProductCatalog では、Factory メソッド ProductFactory.create() を使用して SQLProductRepository オブジェクトのインスタンスを取得します。

インスタンス作成プロセスはファクトリ クラス ProductFactory に委任されますが、初期化プロセスは依然として ProductCatalog クラスで行われます。

理想的には、ProductCatelog クラスがインスタンス化をいつどのようにトリガーするかについて心配する必要はありません。

インスタンス化された ProductRepository クラスを、要求されなくても ProductCatalog に提供したらどうなるでしょうか?

そのため、メイン クラス ECommerceMainApplication は、ファクトリ メソッド ProductFactory.create() を使用して ProductRepository のインスタンスを作成し、このインスタンスは ProductRepositroy クラスのコンストラクターの引数として渡されます。
リーリー

それに応じて ProductCatalog クラスを更新した後


リーリー

これで、ProductCatalog はいつでもどこでも自由に SQLProductRepository オブジェクトを使用できるようになりました。 SQLProductRepository オブジェクトを独自に作成することを心配する必要はなくなりました。

言い換えれば、
依存関係のインスタンス化について心配する ProductCatalog ではなく、ProductCatalog に依存関係

を注入しているということです。

これが
依存性注入の概念です
制御の反転 - IOC

DIP(Dependency Inversion Principle)の一部ではありませんが、密接に関連しています

上記と同じコードでこれを理解してみましょう

クラス ProductCatalog には、ProductRepository オブジェクトを受け取るコンストラクターがありました。

ProductCatalog を呼び出すクラスは、ProductRepository のオブジェクトを提供または注入します。この場合、それは ECommerceMainApplication です。
注: 注入は ProductCatalog クラスの外部で発生しますが、注入は依然としてプログラムのメイン フロー中に発生します。つまり、インジェクションはプログラム実行のメインスレッドで発生します。

すべてのインジェクションを別のスレッドまたは別のコンテキストで完全に実行して、メインの制御フローをインジェクションから完全に分離したい場合はどうすればよいでしょうか?

これは、Spring(Java) のようなフレームワークを使用して実現できます。

Dependency Inversion Principle

Spring はプログラムのメインフローとは異なる独自のコンテキストを実行します
Spring は、クラスに必要な依存関係の注入を処理します。したがって、クラスのオブジェクトをインスタンス化したい場合は、コード内で直接行うのではなく、Spring にクラスのオブジェクトを提供するよう依頼します。
Spring フレームワークは、オブジェクトのインスタンス化に必要なすべての依存関係を調べてから、すべての依存関係を注入し、オブジェクトをインスタンス化し、それをメインの制御フローに返します。
したがって、依存関係注入の制御は Spring フレームワークに完全に委任され、メール制御フローでは発生しません。
この概念は制御の反転 (IOC)と呼ばれ、スプリングは制御の反転コンテナー、または単にIOC コンテナー

と呼ばれます。

以上が依存関係逆転の原則の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ソース:dev.to
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート
私たちについて 免責事項 Sitemap
PHP中国語ウェブサイト:福祉オンライン PHP トレーニング,PHP 学習者の迅速な成長を支援します!