Principe d'inversion de dépendance
Définition
A. Les modules de niveau supérieur ne doivent pas dépendre des modules de niveau inférieur. Les deux types de modules doivent dépendre d'abstractions.
B. Les abstractions ne devraient pas dépendre des détails. Les détails doivent dépendre de l'abstraction.
La première définition inclut le concept de «module». C'est un concept très important sans lequel le DIP ne peut être compris.
module - un ensemble d'éléments fonctionnels interconnectés logiquement
Pour éviter les malentendus, considérez les définitions à l'aide d'un exemple. Disons que nous devons obtenir une liste des livres lus et l'afficher à l'utilisateur. Pour cela, nous utiliserons les classes BooksInteractor et BooksRepository. Nous mettons chacune de ces classes dans son module BI et BR, respectivement. Le module de classe BooksInteractor dépend de la classe BooksRepository.
BooksInteractor'y a besoin d'obtenir une liste de livres de BooksRepository. L'Interactor ne se soucie pas du tout de la manière dont le référentiel reçoit ces données, ce qui signifie que dans ce cas, BooksInteractor est une abstraction pour BooksRepository. Selon la deuxième définition, BooksInteractor (abstraction) ne doit PAS dépendre de BooksRepository (implémentation). D'autre part, le référentiel doit connaître le module BI. Alors que se passe-t-il: l'interacteur doit être à l'intérieur du référentiel? Non, pour inverser les dépendances, il suffit de couvrir le BooksRepository avec l'interface IBooksRepository et de placer cette interface dans le module de classe BooksInteractor. Revenons maintenant à la 1ère définition de DIP et regardons le diagramme.
Regardez, les modules de niveau supérieur (module BI) ne dépendent pas des modules de niveau inférieur (module BR). Et les deux modules dépendent d'une abstraction (de l'interface IBooksRepository). Si vous avez capturé la magie de l'inversion de dépendance en couvrant un référentiel avec une interface, vous comprenez le principe de l'inversion de dépendance. Toutes nos félicitations! La partie la plus difficile que vous comprenez. Vous pouvez en savoir plus sur DIP dans cet article sur Habré.
Inversion de contrôle
Nous avons étudié le concept de «principe d'inversion de dépendance». Passons maintenant à une autre inversion - l'inversion du contrôle. Le concept lui-même est très large et dans la programmation, il peut signifier l'une des trois choses suivantes:
- Inversion des interfaces - délégation de la relation entre les modules à une interface intermédiaire. Où s'applique-t-il? Par exemple, dans le DIP, que nous avons étudié plus tôt.
- — (, DI/IOC ).
- — , . , , — Android . Activity Fragment, .
Dependency Injection
L'injection de dépendances est un mécanisme permettant de transmettre ses dépendances à une classe. Vous rencontrez toujours cela lorsque vous devez passer une dépendance à une autre classe. Il existe plusieurs façons d'injecter des dépendances: via un constructeur (Constructor Injection), via une méthode (Method Injection) et via une propriété (Property Injection). Chacune de ces méthodes est utilisée à ses propres fins. Mais ici, il est important de comprendre que l'injection de dépendances ne fait que passer une dépendance à un constructeur, une méthode ou une propriété.
Considérer les cas extrêmes
- Peut-il y avoir DI sans IoC et DIP? Oui peut-être. Nous créons une instance d'une classe concrète A et la passons à un objet de classe B via un constructeur, une méthode ou une propriété.
- Peut-il y avoir DIP sans IoC? Non, DIP est un moyen d'implémenter l'inversion d'interface dans IoC.
- Peut-il y avoir un DIP sans DI? Oui, nous pouvons lier les modules inférieurs à l'interface. Les classes de module supérieures fonctionneront avec l'abstraction d'interface, mais l'implémentation concrète de la classe de module inférieure sera créée dans le constructeur du module supérieur.
Vous pouvez découvrir les différences entre DIP, DI et IoC d'autres auteurs ici et ici .
Je serais heureux de recevoir vos commentaires et retours!