Maison >développement back-end >tutoriel php >Explication détaillée des exemples Ioc et Di en php
J'utilise le framework ThinkPHP5 récemment. Après avoir regardé son code source, j'ai découvert que l'injection de dépendances (inversion de contrôle) est également utilisée dans de nombreux endroits. Je pense qu'il est nécessaire de parler brièvement avec vous de ce qu'est l'injection de dépendances. qu'est-ce que c'est et comment l'utiliser.
Regardons d'abord un exemple :
<?php class A { public $b; public $c; public function A() { //TODO } public function Method() { $this->b=new B(); $this->c=new C(); $this->b->Method(); $this->c->Method(); //TODO } } class B { public function B() { //TODO } public function Method() { //TODO echo 'b'; } } class C { public function C() { //TODO } public function Method() { //TODO echo 'c'; } } $a=new A(); $a->Method(); ?>
Nous pouvons facilement comprendre le code ci-dessus en une phrase :
La classe A dépend de la classe B et de la classe C
En d'autres termes, si nous devons modifier la classe B ou la classe C dans le futur processus de développement, une fois qu'il s'agit de renommer la fonction, de changer le nombre de paramètres de fonction, ou même en ajustant l'ensemble de la structure de classe, nous ferons les ajustements correspondants à la classe A. L'indépendance de la classe A est perdue, ce qui est très gênant pendant le processus de développement. C'est ce que nous appelons « une chose affecte tout le corps ». ". Si les deux cours sont écrits séparément par deux personnes, oui, des conflits surviennent souvent à ce moment-là. . .
Si on a vraiment besoin de changer les catégories B et C, y a-t-il un moyen de ne pas changer le code de la catégorie A ou de le changer le moins possible ? L'inversion de contrôle est utilisée ici.
Les modules de haut niveau ne doivent pas dépendre de modules de bas niveau, les deux doivent dépendre d'abstractions.
L'inversion de contrôle (IOC) est une idée, et l'injection de dépendances (DI) est une méthode pour mettre en œuvre cette idée.
La première méthode s'appelle : injection de constructeur (cette méthode n'est pas recommandée, mais c'est mieux que de ne pas l'utiliser)
class A { public $b; public $c; public function A($b,$c) { $this->b=$b; $this->c=$c; } public function Method() { $this->b->Method(); $this->c->Method(); } }
La classe client s'écrit ainsi :
$a=new A(new B(),new C()); $a->Method();
Le constructeur de la classe A dépend de la classe B et de la classe C. Il est passé via les paramètres du constructeur. Au moins, cela est réalisé. Un point est que la création de l'objet de classe B b et de l'objet de classe C c a été déplacée en dehors de la classe A, donc une fois la classe B et la classe C modifiées, la classe A n'a pas besoin d'être modifiée. modifié, changez-le simplement dans la classe client
Supposons qu'un jour, nous devions étendre la classe B et créer deux sous-classes de la classe B
class B { public function B() { //TODO } public function Method() { //TODO echo 'b'; } } class B1 extends B { public function B1() { //TODO } public function Method() { echo 'b1'; } } class B2 extends B { public function B2() { //TODO } public function Method() { echo 'b2'; } }
C'est aussi très simple, la classe client est comme ça Écrivez :
$a=new A(new B2(),new C()); $a->Method();
Donc la classe A n'a pas besoin de se soucier des sous-classes de la classe B l'a fait, tant qu'il se préoccupe de la classe client.
La deuxième méthode s'appelle : injection de motif en usine (recommandée)
class Factory { public function Factory() { //TODO } public function create($s) { switch($s) { case 'B': { return new B(); break; } case 'C': { return new C(); break; } default: { return null; break; } } } }
Notre code de classe A est modifié en :
class A { public $b; public $c; public function A() { //TODO } public function Method() { $f=new Factory(); $this->b=$f->create('B'); $this->c=$f->create('C'); $this->b->Method(); $this->c->Method(); //TODO } }
En fait, une petite partie a été découplée, du moins si les constructeurs de classe B et de classe C changent, comme en modifiant les paramètres de fonction, etc. ., il suffit de changer la classe Factory.
L'abstraction ne doit pas dépendre des détails, les détails doivent dépendre de l'abstraction.
Résumer les méthodes des classes B et C et créer une interface
interface IMethod { public function Method(); }
De cette façon, $ en classe A La variable b et la variable $c ne sont plus une variable concrète, mais une variable de type abstrait. Jusqu'au moment de l'exécution, je ne sais pas comment leur méthode est implémentée.
class B implements IMethod { public function B() { //TODO } public function Method() { //TODO echo 'b'; } } class C implements IMethod { public function C() { //TODO } public function Method() { //TODO echo 'c'; } }
Pour résumer quelques points :
1 On déplace la création des objets de classe B et des objets de classe C en classe A. à l'extérieur de la classe A
2. À l'origine, la classe A reposait sur la classe B et la classe C, mais maintenant A dépend de Factory, et Factory dépend de B et C.
Injection de dépendances PHP (DI) et inversion de contrôle ( IoC) )Exemple de tutoriel
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!